Properties

Name: DBMS_RCVMAN 
Status: VALID 
Last modify: 05/12/2002 
Created: 05/12/2002 

Procedures

Name Overload
  BMRADDCORRUPTTABLE 
  FINDARCHIVEDLOGBACKUP 
  FINDOFFLINERANGECOPY 
  FINDVALIDBACKUPSET 
  FINDVALIDBACKUPSET 
  GETALBACKUPHISTORY 
  GETALLBACKUPSET 
  GETARCHIVEDLOG 
  GETARCHIVEDLOG 
  GETBACKUPHISTORY 
  GETBACKUPHISTORY 
  GETBACKUPHISTORY 
  GETBACKUPPIECE 
  GETBACKUPPIECE 
  GETBACKUPPIECE 
  GETBSBACKUPHISTORY 
  GETCHECKPOINT 
  GETCHECKPOINT 
  GETCONFIG 
  GETCONTROLFILECOPY 
  GETCONTROLFILECOPY 
  GETDATAFILE 
  GETDATAFILE 
  GETDATAFILECOPY 
  GETDATAFILECOPY 
  GETDFBACKUPHISTORY 
  GETINCREMENTALSCN 
  GETOFFLINERANGECOPY 
  GETONLINELOG 
  GETPROXYCOPY 
  GETPROXYCOPY 
  INITIALIZE 
  LISTGETARCHIVEDLOGBACKUP 
  LISTGETARCHIVEDLOGCOPY 
  LISTGETBACKUPSETFILES 
  LISTGETCONTROLFILEBACKUP 
  LISTGETCONTROLFILECOPY 
  LISTGETDATAFILEBACKUP 
  LISTGETDATAFILECOPY 
  LISTGETPROXYDATAFILE 
  LISTGETSPFILEBACKUP 
  LISTROLLBACKSEGTABLESPACE 
  LISTTRANSLATEARCHIVEDLOGBACKUP 
  LISTTRANSLATEARCHIVEDLOGBACKUP 
  LISTTRANSLATEARCHIVEDLOGCOPY 
  LISTTRANSLATEBACKUPSETFILES 
  LISTTRANSLATECONTROLFILEBACKUP 
  LISTTRANSLATECONTROLFILECOPY 
  LISTTRANSLATEDATAFILEBACKUP 
  LISTTRANSLATEDATAFILECOPY 
  LISTTRANSLATEDBINCARNATION 
  LISTTRANSLATEPROXYDATAFILE 
  LISTTRANSLATEPROXYDFRECID 
  LISTTRANSLATESPFILEBACKUP 
  PRINTRECOVERYACTIONS 
  REPORTTRANSLATEDFDEL 
  RESETALL 
  RESETDEVICETYPE 
  RESETUNTIL 
  SETALLFLAG 
  SETALLINCARNATIONS 
  SETCOMPLETEDRANGE 
  SETCOMPUTERECOVERYACTIONMASKS 
  SETCOMPUTERECOVERYACTIONMASKS 
  SETDATABASE 
  SETDBINCKEY 
  SETDEBUGOFF 
  SETDEBUGON 
  SETDEVICETYPE 
  SETDEVICETYPEANY 
  SETFROM 
  SETLIKEPATTERN 
  SETRAFLAGS 
  SETSTANDBY 
  SETTAG 
  SETUNTILLOG 
  SETUNTILSCN 
  SETUNTILTIME 
  SET_PACKAGE_CONSTANTS 
  SKIPTABLESPACE 
  TRANSLATEALLBACKUPSET 
  TRANSLATEALLDATAFILE 
  TRANSLATEARCHIVEDLOGCANCEL 
  TRANSLATEARCHIVEDLOGKEY 
  TRANSLATEARCHIVEDLOGNAME 
  TRANSLATEARCHIVEDLOGPATTERN 
  TRANSLATEARCHIVEDLOGSCNRANGE 
  TRANSLATEARCHIVEDLOGSEQRANGE 
  TRANSLATEARCHIVEDLOGTIMERANGE 
  TRANSLATEBACKUPFILE 
  TRANSLATEBACKUPPIECEBSKEY 
  TRANSLATEBACKUPPIECEHANDLE 
  TRANSLATEBACKUPPIECEHANDLE 
  TRANSLATEBACKUPPIECEKEY 
  TRANSLATEBACKUPPIECEKEY 
  TRANSLATEBACKUPPIECETAG 
  TRANSLATEBACKUPSETKEY 
  TRANSLATEBACKUPSETKEY 
  TRANSLATEBACKUPSETKEY 
  TRANSLATEBACKUPSETRECID 
  TRANSLATEBACKUPSETRECID 
  TRANSLATECONTROLFILECOPYNAME 
  TRANSLATECORRUPTLIST 
  TRANSLATEDATABASE 
  TRANSLATEDATAFILE 
  TRANSLATEDATAFILE 
  TRANSLATEDATAFILE 
  TRANSLATEDATAFILECOPYFNO 
  TRANSLATEDATAFILECOPYKEY 
  TRANSLATEDATAFILECOPYKEY 
  TRANSLATEDATAFILECOPYNAME 
  TRANSLATEDATAFILECOPYTAG 
  TRANSLATEONLINELOGS 
  TRANSLATEPROXYCOPYHANDLE 
  TRANSLATEPROXYCOPYHANDLE 
  TRANSLATEPROXYCOPYKEY 
  TRANSLATEPROXYCOPYKEY 
  TRANSLATEPROXYCOPYTAG 
  TRANSLATETABLESPACE 
  TRIMRECOVERYACTIONS 
Total: 120 procedure(s)

Functions

Name Overload Type Length Precision
  COMPUTERECOVERYACTIONS  BINARY_INTEGER     
  DUMPSTATE  VARCHAR2     
  FINDARCHIVEDLOGBACKUP  NUMBER  22   
  FINDCONTROLFILEBACKUP  NUMBER  22   
  FINDCONTROLFILEBACKUP  NUMBER  22   
  GETARCHIVEDLOGBACKUP  BINARY_INTEGER     
  GETCLONENAME  VARCHAR2     
  GETCONTROLFILEBACKUP  NUMBER  22   
  GETINCREMENTALSCN  NUMBER  22   
  GETMAXCOPYNO  NUMBER  22   
  GETOFFLINERANGECOPY  VARCHAR2     
  GETPACKAGEVERSION  VARCHAR2     
  GETPARENTINCARNATION  NUMBER  22   
  GETRCVREC  NUMBER  22   
  GETRECOVERYACTION  BINARY_INTEGER     
  GETRECOVERYACTION  BINARY_INTEGER     
  GETSPFILEBACKUP  NUMBER  22   
  GETUNTILSCN  NUMBER  22   
  GETUNTILTIME  DATE     
  GETVALIDBACKUPSET  NUMBER  22   
  ISBACKUPTYPEMATCH  NUMBER  22   
  ISDEVICETYPEALLOCATED  NUMBER  22   
  ISSTATUSMATCH  NUMBER  22   
  LISTGETARCHIVEDLOGBACKUP  NUMBER  22   
  LISTGETARCHIVEDLOGBACKUP  NUMBER  22   
  LISTGETARCHIVEDLOGCOPY  NUMBER  22   
  LISTGETCONTROLFILEBACKUP  NUMBER  22   
  LISTGETCONTROLFILECOPY  NUMBER  22   
  LISTGETDATAFILEBACKUP  NUMBER  22   
  LISTGETDATAFILECOPY  NUMBER  22   
  LISTGETDBINCARNATION  NUMBER  22   
  LISTGETPROXYDATAFILE  NUMBER  22   
  LISTGETTABLESPACE  NUMBER  22   
  REPORTGETDFDEL  NUMBER  22   
  REPORTGETDFDEL  NUMBER  22   
  STAMP2DATE  DATE     
  WASFILEOFFLINE  NUMBER  22   
Total: 37 function(s)

Used by

Owner Name Type
RMAN  DBMS_RCVCAT  PACKAGE BODY 
RMAN  DBMS_RCVMAN  PACKAGE BODY 
Total: 2 used by reference(s)

DDL


  CREATE OR REPLACE PACKAGE "RMAN"."DBMS_RCVMAN" is
-- DE-HEAD       <- tell SED where to cut
----------------------------------------
-- PUBLIC VARIABLES AND TYPES SECTION --
----------------------------------------
TRUE#  CONSTANT number := 1;
FALSE# CONSTANT number := 0;
-- The values here must never be changed, because the 8.0 rman executables have
-- these values hard-coded in the krmkbt enum in krmk.h.  The setFrom procedure
-- in particular is using hard-coded values.
-- The 8.1.5 rman executable calls a procedure, set_package_constants, that
-- re-assigns these constants to whatever the package needs them to be, then
-- queries the package for their new values.  The 8.1.5 rman does not care
-- what the values are, however, the cursor used by reportGetDFDel used to use
-- these values to perform an order-by to return rows in preference order.
-- The preference order is used to decide which ones to delete.
-- As of 8.1.6, the order-by in reportGetDFDel is independant of these values.
-- The 8.1.6 rman does not use these values at all, except in setFrom.
-- However, for backwards compatibility with the 8.1.5 RMAN, these must remain
-- as public package constants.
COPY                  number := 1; -- any image copy of a file
FULL_DF_BACKUP        number := 2; -- datafile in a full backup set
INCREMENTAL_DF_BACKUP number := 3; -- datafile in an incr backup set
BACKUP                number := 4; -- any file in a backup set
OFFLINE_RANGE         number := 5; -- an offline range
CUMULATIVE            number := 6; -- cumulative incremental - for LIST only
PROXY                 number := 7; -- any proxy copy of a file
-- Recovery Action Kinds (Obsolete as of 8.1.6) --
implicitOfflRange CONSTANT NUMBER := 2**0;
cleanRange        CONSTANT NUMBER := 2**1;
applyOfflRange    CONSTANT NUMBER := 2**2;
dfCopy            CONSTANT NUMBER := 2**3;
proxyFull         CONSTANT NUMBER := 2**4;
buSet             CONSTANT NUMBER := 2**5;
applyIncremental  CONSTANT NUMBER := 2**6;
redo              CONSTANT NUMBER := 2**7;
-- kind masks
maxKind           CONSTANT NUMBER := redo;            -- last real kind above
allKind           CONSTANT NUMBER := (maxKind*2) - 1; -- all real backup types
fullKind          CONSTANT NUMBER := dfCopy + proxyFull + buSet;
tagKind           CONSTANT NUMBER := fullKind + applyIncremental;
-- pseudo kinds
deletedKind       CONSTANT NUMBER := maxKind*2;      -- action deleted
----------------------------------
-- Backupset Availability Masks --
----------------------------------
BSavailable     CONSTANT BINARY_INTEGER := 2**0;
BSunavailable   CONSTANT BINARY_INTEGER := 2**1;
BSdeleted       CONSTANT BINARY_INTEGER := 2**2;
BSexpired       CONSTANT BINARY_INTEGER := 2**3;
-- BSpartial_avail is a backupset validation mask and NOT a backuppiece
-- filter.  For eg. to get 'A', 'U', 'X' pieces and to enable validation
-- to succeed for partially available backupset use
-- BSpartial_avail + BSavailable + BSunavailable + BSexpired.
BSpartial_avail CONSTANT BINARY_INTEGER := 2**4;
----------------------
-- BackupType Mask ---
----------------------
BSdatafile_full  CONSTANT BINARY_INTEGER := 2**0;
BSdatafile_incr  CONSTANT BINARY_INTEGER := 2**1;
BSarchivelog     CONSTANT BINARY_INTEGER := 2**2;
---------------------------
-- ControlfileType Mask ---
---------------------------
BScfile_all      CONSTANT BINARY_INTEGER := 2**0;      -- shouldn't be altered
BScfile_auto     CONSTANT BINARY_INTEGER := 2**1;
---------------------
-- Datafile Record --
---------------------
TYPE dfRec_t IS RECORD
(
   dfNumber             number,
   dfCreationSCN        number,
   dfCreationTime       date,
   fileName             varchar2(1024),
   tsName               varchar2(30),
   tsNumber             number,
   status               number,
   blocks               number,
   blockSize            number,
   kbytes               number,
   unrecovSCN           number,
   stopSCN              number,
   readOnly             number,
   rfNumber             number,
   inBackup             number,     -- if greater than 0 then
                                    -- included_in_database_backup is set
   auxName              varchar2(1024)
);
-------------------------
-- Archived Log Record --
-------------------------
TYPE alRec_t IS RECORD
(
   key                  number,
   recid                number,
   stamp                number,
   thread               number,
   sequence             number,
   fileName             varchar2(1024),
   lowSCN               number,
   lowTime              date,
   nextSCN              number,
   nextTime             date,
   rlgSCN               number,
   rlgTime              date,
   blocks               number,
   blockSize            number,
   status               char(1),
   compTime             date,
   duplicate            number
);
-- All of the queries which return data about a backup/imagecopy/proxycopy
-- select into a rcvRec_t record type.  We have standardized all of our
-- queries to have a common select-list and the results of the queries are
-- returned through a common public package function.  The reason for this is
-- so that krmk.pc can populate its internal data structures consistantly,
-- regardless of what particular procedure it has called to query the catalog.
-- By having all queries select into the same record type, we can ensure
-- that all queries use the same select list.  Any new fields that get added
-- to this record will require updating the select lists of all queries.
-- Failure to make the correct updates will result in PLSQL giving an error
-- when the package body is re-created, so the error will be easily detected
-- without the need to run any test suite.
-- The record is divided into three sections.  These correpond to
-- three krmk.h data structures which will be populated with the data
-- from this record.  Refer to krmk.h for a description of the purpose
-- of each of these three data strucutres.
-- Think of this as:  the container acts on the object.
---------------------
-- Recovery Record --
---------------------
TYPE rcvRec_t IS RECORD
(
   -- *** Recovery Container Section ***
   type_con             number(3),      -- recovery container type
   key_con              number(15),     -- primary key
   recid_con            number(10),     -- recid
   stamp_con            number(10),     -- stamp
   setStamp_con         number(10),     -- set count if backup set (null)
   setCount_con         number(10),     -- set stamp if backup set (null)
   bsRecid_con          number(10),     -- backup set recid (null)
   bsStamp_con          number(10),     -- backup set stamp (null)
   bsKey_con            number(15),     -- backup set key (null)
   bsLevel_con          number(1),      -- backup set level (null)
   bsType_con           char(1),        -- backup set type
   elapseSecs_con       number(10),     -- backup set elapse seconds (null)
   pieceCount_con       number(5),      -- backup set piece count (null)
   fileName_con         varchar2(1024), -- filename if a copy (or) piece (null)
   tag_con              varchar2(32),   -- tag (null)
                                        -- filled in by addAction() for
                                        -- backup sets
   copyNumber_con       number(3),      -- backup set copy# (null) maxlimit 256
                                        -- filled in by addAction() only
   status_con           char(1),        -- status (null)
   blocks_con           number(10),     -- size of file in blocks (null)
   blockSize_con        number(5),      -- block size (null)
   deviceType_con       varchar2(255),  -- device type required (null)
                                        -- filled in by addAction() for
                                        -- backup sets
   compTime_con         date,           -- completion time
   cfCreationTime_con   date,           -- controlfile creation time if
                                        -- offline range (null)
   pieceNumber_con      number,
   bpCompTime_con       date,
   -- *** Recovery Action Section ***
   type_act             number(2),      -- recovery action type
   fromSCN_act          number(15),
   toSCN_act            number(15),
   toTime_act           date,
   rlgSCN_act           number(15),
   rlgTime_act          date,
   dbincKey_act         number(15),
   level_act            number(1),
   -- *** Recovery Object Section ***
   dfNumber_obj         number(6),
   dfCreationSCN_obj    number(15),
   cfSequence_obj       number(15),    -- controlfile autobackup sequence
   cfDate_obj           date,          -- controlfile autobackup date
   logSequence_obj      number(10),
   logThread_obj        number(4),
   logRlgSCN_obj        number(15),
   logRlgTime_obj       date,
   logLowSCN_obj        number(15),
   logLowTime_obj       date,
   logNextSCN_obj       number(15),
   logNextTime_obj      date,
   -- *** Retention Policy Section ***
   keep_options         number(4),
   keep_until           date,
   -- *** Optimization Action Section ***
   afzSCN_act           number(15),
   rfzTime_act          date,
   rfzSCN_act           number(15)
);
------------------------------
-- Recovery Container Types --
------------------------------
-- NOTE:  Order is important, it is used in an ORDER BY.
offlineRangeRec_con_t   CONSTANT NUMBER := 2**0;
proxyCopy_con_t         CONSTANT NUMBER := 2**1;
imageCopy_con_t         CONSTANT NUMBER := 2**2;
backupSet_con_t         CONSTANT NUMBER := 2**3;
deleted_con_t           CONSTANT NUMBER := 2**8;
-- Masks
backupMask_con_t        CONSTANT NUMBER := proxyCopy_con_t + imageCopy_con_t +
                                           backupSet_con_t;
tagMask_con_t           CONSTANT NUMBER := proxyCopy_con_t + imageCopy_con_t +
                                           backupSet_con_t;
---------------------------
-- Recovery Action Types --
---------------------------
full_act_t              CONSTANT NUMBER := 2**0;
incremental_act_t       CONSTANT NUMBER := 2**1;
redo_act_t              CONSTANT NUMBER := 2**2;
offlineRange_act_t      CONSTANT NUMBER := 2**3;
cleanRange_act_t        CONSTANT NUMBER := 2**4;
implicitRange_act_t     CONSTANT NUMBER := 2**5;
spanningRange_act_t     CONSTANT NUMBER := 2**6;
-----------------------------------------
-- Recovery Record Returning Functions --
-----------------------------------------
-- These defines are used as the funCode arg to getRcvRec to tell it which
-- function it should call.  We do this so that krmk.pc can have a single
-- interface routine for getting a rcvRec_t.
getCfCopy               CONSTANT NUMBER := 0;
getDfCopy               CONSTANT NUMBER := 1;
getAnyProxy             CONSTANT NUMBER := 2;
getCfBackup             CONSTANT NUMBER := 3;
listCfCopy              CONSTANT NUMBER := 4;
listDfCopy              CONSTANT NUMBER := 5;
listCfBackup            CONSTANT NUMBER := 6;
listDfBackup            CONSTANT NUMBER := 7;
listAlBackup            CONSTANT NUMBER := 8;
listDfProxy             CONSTANT NUMBER := 9;
getRecovAction          CONSTANT NUMBER := 10;
getAlBackup             CONSTANT NUMBER := 11;
listAlCopy              CONSTANT NUMBER := 12;
listBSet                CONSTANT NUMBER := 13;
getSfBackup             CONSTANT NUMBER := 14;
listSfBackup            CONSTANT NUMBER := 15;
getAllBSet              CONSTANT NUMBER := 16;
-----------------------
-- Backup Set Record --
-----------------------
TYPE bsRec_t IS RECORD
(
   recid                number,
   stamp                number,
   key                  number,
   setStamp             number,
   setCount             number,
   bsType               char(1),
   level                number,
   elapseSecs           number,
   compTime             date,
   status               char(1),
   pieceCount           number,
   keep_options         number(4),
   keep_until           date
);
------------------------
-- Backup Piece Record --
-------------------------
TYPE bpRec_t IS RECORD
(
   recid                number,
   stamp                number,
   key                  number,
   bskey                number,
   setStamp             number,
   setCount             number,
   pieceNumber          number,
   copyNumber           number,
   status               char(1),
   compTime             date,
   handle               varchar2(1024),
   tag                  varchar2(32),
   deviceType           varchar2(255)
);
---------------------------------
-- Backupset Validation Record --
---------------------------------
TYPE validBackupSetRec_t IS RECORD
(
   deviceType   varchar2(255),
   tag          varchar2(32),                   -- may be null
   copyNumber   number,                         -- null if code 2 or 3
   code         number                          -- 1 => same copy#
                                                -- 2 => mix of copy#s, but
                                                --      same tag
                                                -- 3 => mix of copy#s and tags
);
--------------------
-- backup history --
--------------------
TYPE bhistoryRec_t IS RECORD
(
   key             number,
   device_type     varchar2(255),
   dfNumber        number,
   create_scn      number,
   reset_scn       number,
   reset_time      date,
   ckp_scn         number,
   stop_scn        number,
   logThread       number,
   logSequence     number,
   setStamp        number,
   setCount        number,
   compTime        date,
   nbackups        number
);
-----------------------------------------------------
-- PUBLIC FUNCTION/PROCEDURE SPECIFICATION SECTION --
-----------------------------------------------------
----------------------------------------
-- Debugging functions and procedures --
----------------------------------------
FUNCTION dumpState(
   lineno IN number)
RETURN varchar2;
PROCEDURE setDebugOn;
PROCEDURE setDebugOff;
----------------------------
-- Package Initialization --
----------------------------
-- This is a vestigal function that was released to customers in 8.1.3 Beta.
-- It is no longer called, and is no longer needed, but must still be here
-- because this version of the package may be called by an 8.1.3 rman
-- executable.
PROCEDURE initialize(rman_vsn IN number);
-- Used by 8.1.5 to re-assign the order of the backup_type constants to their
-- correct order.  This procedure is not called by 8.1.4-, so the constants
-- will reamin set to the above values for those executables.
PROCEDURE set_package_constants;
-----------------------
-- Utility functions --
-----------------------
FUNCTION stamp2date(stamp IN number) RETURN date;
------------------------------
-- Set Database Incarnation --
------------------------------
-- setDatabase selects which target database subsequent dbms_rcvman
-- procedures operate on. Note that only the current incarnation can be
-- selected. If the target database or its current incarnation is not
-- registered then setDatabase will fail.
-- setDatabase sets the package state variables to point to the selected
-- database and its current incarnation.
-- The settings will be valid until the end of the session unless setDatabase
-- is called again
-- When dbms_rcvman package executes against the target database controlfile,
-- setDatabase just returns without doing anything.
-- Input parameters:
--   db_id
--     the value of kccfhdbi from the controlfile of the target database
--   db_name
--     the name of the database
--   reset_scn
--     the resetlogs SCN of this database
--   reset_time
--     the resetlogs time
-- Exceptions:
--   DATABASE_NOT_FOUND (ORA-20001)
--     No database with the given db_id was found in the recovery catalog
--     The database must be registered using registerDatabase first
--   DATABASE_INCARNATION_NOT_FOUND (ORA-20003)
--     No database incarnation matches the given arguments
--     The database incarnation must be registered using resetDatabase first
PROCEDURE setDatabase(
   db_name    IN varchar2
  ,reset_scn  IN number
  ,reset_time IN date
  ,db_id      IN number);
-- setDbincKey used in lieu of setDatabase for when SET DBID command is
-- issued.
PROCEDURE setDbincKey(
   key IN number);
-- getParent Incarnation returns the parent incarnation.  If resetlogs_change#
-- is NULL on input, then the current incarnation is returned.  Returns TRUE
-- if a row was returned, otherwise returns FALSE.
FUNCTION getParentIncarnation(
   resetlogs_change# IN OUT number
  ,resetlogs_time    IN OUT date)
RETURN number;
-- getCheckpoint gets and returns the highest recovery catalog checkpoint SCN
-- for FULL checkpoints.  This SCN indicates how current the datafilenames and
-- lognames in the recovery catalog are.  This SCN can be compared with a
-- backup controlfile SCN to decide which name to use if they differ.
PROCEDURE getCheckpoint(
   scn OUT number
  ,seq OUT number);
-- This version of getCheckpoint is only used internally by
-- dbms_rcvcat.cleanupCKP, to find out which rows can't be deleted from ckp.
PROCEDURE getCheckpoint(
   scn       OUT number
  ,seq       OUT number
  ,ckp_key_1 OUT number
  ,ckp_key_2 OUT number);
-------------------
-- Query Filters --
-------------------
-- setCompletedRange sets completedBefore and/or completedAfter filters for
-- use by computeRecoveryActions.
-- setLikePattern sets fileName patter for computeRecoveryActions.
--
-- setUntilTime, setUntilScn, setUntilLog, resetUntil These procedures are
-- used to inform dbms_rcvman of an until_clause.  The setUntil remains in
-- effect until another setUntil has been called, or until resetUntil has been
-- called.  If none of these have been called, then all queries for name
-- translation, restore, and recovery should assume that a complete recovery
-- is being done.  Otherwise, all restore and recovery queries should limit
-- their replies to backup sets and datafile copies that are appropriate for
-- use in an incomplete recovery until the specified until condition.  Name
-- translations should be done relative to the specified epoch.
--
-- "appropriate" means that the fuzziness of the backup datafile or datafile
-- copy ends at an SCN less than the untilChange SCN (for untilChange), or the
-- low SCN of the specified log (for untilLog), or the fuzziness timestamp is
-- less than the specified time (for unttime).  Note that datafiles have three
-- kinds of fuzziness, all of which must be less than the specified SCN or
-- time.  If the fuzziness of a datafile is unknown, then it should be
-- ignored.
--
-- The setUntil procedures will signal an error when executed against
-- the target database controlfile. The resetUntil procedure can be
-- executed against the controlfile, it but doesn't have any effect.
-- Input parameters:
--   unttime
--     The incomplete recovery will stop when this timestamp is reached
--     in the redo log.
--   scn
--     The incomplete recovery will stop when this scn is reached in the redo
--     log.
--   sequence#, thread#
--     The incomplete recovery will stop when this log becomes the very next
--     log to be applied.
--
-- Exceptions:
--   NO_RECOVERY_CATALOG (ORA-20300)
--     this operation is not supported without the recovery catalog
--   SEQUENCE_IS_NULL (ORA-20205)
--     A null log sequence# was given
--   LOG_MISSING (ORA-20206)
--     No log with the give thread# and sequence# was found
PROCEDURE setCompletedRange(
   after  IN date
  ,before IN date);
PROCEDURE setLikePattern(
   pattern IN varchar2);
-- Obsolete as of 8.1.6
PROCEDURE setAllFlag(
   flag IN boolean);
PROCEDURE setAllIncarnations(
   flag IN boolean);
PROCEDURE setUntilTime(
   unttime IN date);
PROCEDURE setUntilScn(
   scn IN number);
PROCEDURE setUntilLog(
   sequence# IN number
  ,thread#   IN number);
FUNCTION getUntilTime return date;
FUNCTION getUntilScn return number;
PROCEDURE resetUntil;
-- setFrom is used to limit the potential restore candidates to either
-- backup sets or datafile copies, or to allow either kind of file to
-- be used.
--
-- Input parameters:
--   restorefrom
--     One of BACKUP, COPY, or NULL.
PROCEDURE setFrom(
   restorefrom IN number DEFAULT NULL);
-- setDeviceType specifies the type of an allocated device.  It is called 1 or
-- more (up to 8) times , depending on the number of different device types
-- that are allocated.  dbms_rcvman should return only files that can be
-- accessed through one of the device types specifed through this call.
--
-- Input parameters:
--   type
--     type of the device
-- Exceptions:
--   NULL_DEVICE_TYPE
--     A null device type was specied
--   TOO_MANY_DEVICE_TYPES
--     At most 8 device types can be specified
PROCEDURE setDeviceType(
   type IN varchar2);
-- setDeviceTypeAny is an alternative to setDeviceType.  It causes dbms_rcvman
-- to return a backup set on ANY device type.
PROCEDURE setStandby(
   stby IN boolean);
PROCEDURE setDeviceTypeAny;
-- resetDeviceType resets the list of device types to null.
PROCEDURE resetDeviceType;
-- setTag is used to limit the restore candidates to backups and copies with
-- the given tag. If the tag is NULL then all backups and copies are searched
-- by the find functions.
--
-- Input parameters:
--   tag
--     tag of the datafile copies to be translated
--     The tag must be passed in uppercase ### ok?
PROCEDURE setTag(tag IN varchar2 DEFAULT NULL);
-- resetAll calls resetUntil, setFrom, resetDevice and setTag to reset
-- everything.
PROCEDURE resetAll;
---------------------------
-- Backup Set Validation --
---------------------------
-- Use the findValidBackupSetRec public variable to save a backupset record
-- for later use as an input argument to this procedure.
findValidBackupSetRcvRec rcvRec_t;              -- place to save a rcvRec_t
PROCEDURE findValidBackupSet(
   backupSetRec            IN     rcvRec_t
  ,deviceType              IN     varchar2       DEFAULT NULL
  ,tag                     IN     varchar2       DEFAULT NULL
  ,available               IN     number         DEFAULT TRUE#  -- for compat.
  ,unavailable             IN     number         DEFAULT FALSE# -- for compat.
  ,deleted                 IN     number         DEFAULT FALSE# -- for compat.
  ,expired                 IN     number         DEFAULT FALSE# -- for compat.
  ,availableMask           IN     binary_integer DEFAULT NULL); -- for compat.
findValidBackupSetBsRec  bsRec_t;               -- place to save a bsRec_t
-- Obsolete as of 8.1.7
PROCEDURE findValidBackupSet(
   backupSetRec            IN     bsRec_t
  ,deviceType              IN     varchar2       DEFAULT NULL
  ,tag                     IN     varchar2       DEFAULT NULL
  ,available               IN     number         DEFAULT TRUE#  -- for compat.
  ,unavailable             IN     number         DEFAULT FALSE# -- for compat.
  ,deleted                 IN     number         DEFAULT FALSE# -- for compat.
  ,expired                 IN     number         DEFAULT FALSE# -- for compat.
  ,availableMask           IN     binary_integer DEFAULT NULL); -- for compat.
FUNCTION getValidBackupSet(
   validBackupSetRec            OUT validBackupSetRec_t
  ,checkDeviceIsAllocated       IN  number DEFAULT FALSE#)
RETURN number;                                  -- TRUE# -> got a record
                                                -- FALSE# -> no_data_found
---------------------
-- Get an rcvRec_t --
---------------------
-- This function is a cover function for all procedures/functions that
-- return a rcvRec_t.  It routes the call to the correct procedure.  It
-- is provided for the convienence of krmk.pc.  The function return value
-- is whatever the underlying function returns.  If we call a procedure,
-- then getRcvRec returns 0.  Refer to the funCode list above in the
-- types/variables section.
FUNCTION getRcvRec(
   funCode      IN number
  ,rcvRec       OUT rcvRec_t
  ,callAgain    OUT number)
RETURN number;
--------------------------
-- Datafile Translation --
--------------------------
-- translateTableSpace translates a tablespace name into a list of datafile
-- numbers.  translateDataBase translates the database into a list of datafile
-- numbers in the database excluding datafiles belonging to tablespaces
-- specified using skipTableSpace.  The translation is performed relative to
-- epoch setting currently in use.  getDataFile is used to obtain the datafile
-- numbers, one at a time until null is returned.
-- When doing the translation relative to current time the client should
-- ensure that recovery catalog is up-to-date. When doing translations
-- relative to an point-in-time in the past two potential anomalies may
-- show up.
--
-- 1) files belonging to a tablespace that was dropped before the point-in-time
-- may be returned since the drop_scn and drop_time are approximations.
-- As a result of this point-in-time recovery will restore and recover
-- a tablespace which will be dropped before the database is opened.
-- No real harm, just extra work for the recovery. And this won't happen
-- if rcvcat is resynced immediatly after dropping a tablespace.
-- 2) A tablespace which is created and dropped between two consecutive
-- recovery catalog resyncs will never be recorded in the rcvcat. It is
-- conceivable that such a tablespace existed at the intended point-in-time.
-- As a result the tablespace will not be recovered and must be dropped
-- after the database is opened. The worst case scenario is that a rollback
-- segment was also created in this tablespace. The recovered database
-- might fail to rollback some transactions. Again, this won't happen if
-- rcvcat is always resynced after creating a tablespace.
-- PS. These anomalies won't occur if the point-in-time is chosen to be
-- a rcvcat checkpoint.
-- Input parameters:
--   ts_name
--     name of the tablespace to be translated or skipped.
--     The name must be in uppercase
-- Exceptions:
--   TABLESPACE_DOES_NOT_EXIST (ORA-20202)
--     the tablespace to be translated does not exists (does not have any
--     datafiles). Check that the recovery catalog is current.
--   TRANSLATION_IN_PROGRESS (ORA-20203)
--     the previous translation conversation is still in progess.
--     To terminate get all datafiles with getDataFile.
--   TRANSLATION_NOT_IN_PROGRESS (ORA-20204)
--     getDataFile was called with no translation in progress
PROCEDURE translateDatabase(
   sinceUntilSCN IN number DEFAULT NULL);
PROCEDURE skipTableSpace(
   ts_name IN varchar2);
PROCEDURE translateTablespace(
   ts_name IN varchar2);
-- translateDataFile translates the datafile name/number into
-- a datafile number and creation SCN and filename.  getDataFile must
-- be called to obtain the translation info, just as for the other translate
-- functions.
-- Unlike the other translation functions, translateDatafile by name is always
-- performed relative to current time.  If an until setting is in effect,
-- and if the filename is ambiguous, then an exception is raised.  Ambiguous
-- means that the filename refers to different datafile at the until time than
-- it does at the current time.  This happens only when a filename has been
-- reused.  When fno and ckpscn are passed, the filename and other info as of
-- that scn is returned.
-- Input parameters:
--   fname
--     name of the datafile to be translated.
--     The name must be a normalized filename.
--   fno
--     The datafile number.  If the datafile number was not in use at the
--     until time, then an exception is raised.
-- Exceptions:
--   DATAFILE_DOES_NOT_EXIST (ORA-20201)
--     the datafile to be translated does not exists
--     Check that the recovery catalog is current.
PROCEDURE translateDataFile(
   fname IN varchar2);
PROCEDURE translateDatafile(
   fno   IN number);
PROCEDURE translateDatafile(
   fno    IN number
  ,ckpscn IN number);
-- translateAllDatafile returns a list of all datafiles that ever
-- existed in this database.
PROCEDURE translateAllDatafile;
PROCEDURE translateCorruptList;
PROCEDURE getDatafile(
   dfRec     OUT dfRec_t
  ,oldClient IN  boolean DEFAULT FALSE);
-- Obsolete as of 8.1.6
PROCEDURE getDataFile(
   file#        OUT number
  ,crescn       OUT number
  ,creation_time OUT date
  ,fname        OUT varchar2
  ,ts_name      OUT varchar2
  ,status       OUT number
  ,blksize      OUT number
  ,kbytes       OUT number
  ,blocks       OUT number
  ,unrecoverable_change# OUT number
  ,stop_change# OUT number
  ,read_only    OUT number);
----------------------------
-- Online Log Translation --
----------------------------
-- translateOnlineLogs translates the database to a list of online redo logs.
-- The translation is always performed relative to current epoch.
PROCEDURE translateOnlineLogs;
PROCEDURE getOnlineLog(
   fname        OUT varchar2
  ,thread#      OUT number
  ,group#       OUT number);
-----------------------------
-- Archivedlog Translation --
-----------------------------
-- translateArchivedLogKey translates the archived log key to a archived
-- log recid and stamp in V$ARCHIVED_LOG.
-- translateArchivedLogRange* procedures translate a specified
-- archive log range to a list of archived logs.
-- getArchivedLog is used to get the recid and stamp for each archived log,
-- one at a time until null is returned.
-- The available, unavailable and deleted parameters are used to limit
-- the translation to archived logs with the desired status. For example,
-- only available archived logs can be backed up, but unavailable and deleted
-- archived logs can be restored from backups.
-- The duplicates parameter controls whether the translation returns all
-- archived logs or eliminates duplicate ones. Archived logs that have the
-- same thread#, sequence# and low_scn are considered duplicates. (duplicate
-- archived logs are usually created by copying archived logs).
-- Note that only archived logs recorded in the recovery catalog or
-- controlfile file are returned. If there is an archived log that belongs
-- to the range but is not known, there will be a "hole" in the range.
-- Input parameters:
--    al_key
--      key of the archived log record in the recovery catalog
--   thread#
--     return only logs that belong to this thread#
--     if NULL return logs for all threads
--   fromseq#
--     lowest log sequence number in the range
--   toseq#
--     highest log sequence number in the range
--   fromtime
--     exclude logs that were switched out before fromtime
--   totime
--     exclude logs that were switched in after totime
--   fromscn
--     exclude logs that were switched out before fromscn
--   toscn
--     exclude logs that were switched in after toscn
--   pattern
--     return only archived logs whose filename match the pattern
--     The pattern is matched against normalized filenames ### ok?
--   available
--     if TRUE (1) return available archived logs
--   unavailable
--     if TRUE (1) return unavailable archived logs
--   deleted
--     if TRUE (1) return deleted archived logs
--   online
--     if TRUE (1) return also inspected online logs (in addition to
--     archived logs)
--   duplicates
--     if TRUE (1) return all archived logs
--     if FALSE (0) eliminate duplicate archived logs
-- Output parameters:
--    recid
--      recid of the archived log record (in V$ARCHIVED_LOG)
--    stamp
--      stamp of the archived log record (in V$ARCHIVED_LOG)
--    thread#
--    sequence#
--    low_scn
--    fname
--    reset_scn
--    block_size
-- Exceptions:
--  NO_RECOVERY_CATALOG (ORA-20300)
--    this operation is not supported without the recovery catalog
--  ARCHIVED_LOG_DOES_NOT_EXIST
--    the key does not match any archived log
--   TRANSLATION_IN_PROGRESS (ORA-20203)
--     the previous translation conversation is still in progess.
--     To terminate get all datafiles with getArchivedLog.
--   TRANSLATION_NOT_IN_PROGRESS (ORA-20204)
--     getArchivedLog was called with no translation in progress
--   THREAD_IS_NULL (ORA-20210)
--     a null thread# was passed to translateArchivedLogSeqRange
--   HIGH_SEQUENCE_IS_NULL
--     a null toseq# was passed to translateArchivedLogSeqRange
--   UNTIL_TIME_IS_NULL (ORA-20212)
--     a null totime was passed to translateArchivedLogTimeRange
--   UNTIL_SCN_IS_NULL (ORA-20213)
--     a null toscn was passed to translateArchivedLogSCNRange
--   ARCHIVED_LOG_RANGE_IS_EMPTY
--     the specified range doesn't contain any archived log
------------------------------
-- Archived Log Translation --
------------------------------
PROCEDURE getArchivedLog(
   alRec       OUT alRec_t
  ,closeCursor IN  boolean DEFAULT FALSE);
PROCEDURE translateArchivedLogKey(
   al_key       IN  number
  ,available    IN  number       DEFAULT 1 -- ignored (for compatability)
  ,unavailable  IN  number       DEFAULT 1 -- ignored (for compatability)
  ,deleted      IN  number       DEFAULT 1 -- ignored (for compatability)
  ,online       IN  number       DEFAULT 1 -- ignored (for compatability)
  ,recid        OUT number
  ,stamp        OUT number
  ,thread#      OUT number
  ,sequence#    OUT number
  ,low_scn      OUT number
  ,reset_scn    OUT number
  ,block_size   OUT number
  ,fname        OUT varchar2
  ,needstby     IN number        DEFAULT NULL);
PROCEDURE translateArchivedLogName(
   fname        IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number                        -- ignored
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL);
PROCEDURE translateArchivedLogSeqRange(
   thread#      IN number
  ,fromseq#     IN number
  ,toseq#       IN number
  ,pattern      IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number                        -- ignored
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL);
PROCEDURE translateArchivedLogTimeRange(
   thread#      IN number
  ,fromTime     IN date
  ,toTime       IN date
  ,pattern      IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number                        -- ignored
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL);
PROCEDURE translateArchivedLogSCNRange(
   thread#      IN number
  ,fromSCN      IN number
  ,toSCN        IN number
  ,pattern      IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL);
PROCEDURE translateArchivedLogPattern(
   pattern      IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number                        -- ignored
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL);
PROCEDURE translateArchivedLogCancel;
-- translateBackupPieceKey looks up a backup piece by primary key.
-- translateBackupPieceHandle looks up a backup piece by handle and deviceType.
-- translatebackupPieceTag looks up backup pieces by tag.
-- The available are unavailable parameters are used to limit the translation
-- to backup pieces with the desired status. For example, only available
-- backup pieces can be backed up, but unavailable pieces can be made
-- available.  Deleted backup pieces are never returned.
-- Input parameters:
--    bp_key
--      key of the backup piece record in the recovery catalog
--    handle
--      backup piece handle
--    device type
--      device type on which the backup piece resides
-- Exceptions:
--   NO_RECOVERY_CATALOG (ORA-20300)
--     this operation is not supported without the recovery catalog
--   BACKUP_PIECE_DOES_NOT_EXIST
--     the key does not match any backup piece
--   BACKUP_PIECE_HANDLE_IS_AMBIGUOUS
--     the key does not match any backup piece
-- Obsolete as of 8.1.6
PROCEDURE getArchivedLog(
   recid        OUT number
  ,stamp        OUT number
  ,thread#      OUT number
  ,sequence#    OUT number
  ,low_scn      OUT number
  ,nxt_scn      OUT number
  ,fname        OUT varchar2
  ,reset_scn    OUT number
  ,block_size   OUT number
  ,blocks       OUT number);
---------------------------------
-- Controlfilecopy Translation --
---------------------------------
-- translateControlFileCopyName translates a control file name into a list of
-- control file copies.
-- Input parameters:
--   fname
--     name of the controlfile copy to be translated.
--     The name must be a normalized filename
-- Exceptions:
--   CONTROLFILE_COPY_DOES_NOT_EXIST
--     The filename does not match any controlfile copy
PROCEDURE translateControlFileCopyName(
   fname        IN varchar2
  ,available    IN number         DEFAULT NULL -- for compatability
  ,unavailable  IN number         DEFAULT NULL -- for compatability
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL); -- for compatability
PROCEDURE getControlFileCopy(
   rcvRec       IN OUT rcvRec_t);
-- Obsolete as of 8.1.6
PROCEDURE getControlFileCopy(
   recid        OUT number
  ,stamp        OUT number
  ,reset_scn    OUT number
  ,ckp_scn      OUT number
  ,block_size   OUT number);
------------------------------
-- Datafilecopy Translation --
------------------------------
PROCEDURE getDataFileCopy(
   rcvRec       OUT rcvRec_t
  ,closeCursor  IN  boolean DEFAULT FALSE);
-- translateDataFileCopyKey translates the datafile copy key into a
-- datafile copy recid and stamp in V$DATAFILE_COPY.
-- translateDataFileCopyNumber translates a file number and (optional) tag
-- to a datafile copy recid and stamp. Not used currently in 8.0.
-- translatedDataFileCopyName translates the datafile copy name into a
-- a list of datafile copies and getDataFileCopy returns the recid and stamp
-- of each datafile copy. The duplicates parameter controls whether
-- getDataFileCopy returns all matching datafile copies or just the most
-- recent copy (highest stamp in rcvcat or highest recid in controlfile).
-- translateDataFileCopyTag translates the tag into a list of datafile
-- copies and getDataFileCopy returns the recid and stamp of each datafile copy
-- one at a time until null is returned.
-- translateDataFileCopyFno translates a file number into a list of datafile
-- copies.  getDataFileCopy returns the recid and stamp of each datafile
-- copy one at at time until null is returned.  The duplicates parameter
-- controls whether getDataFileCopy returns all matching datafile copies or
-- just the most recent copy (highest stamp in rcvcat or highest recid in
-- controlfile).
-- The available are unavailable parameters are used to limit the translation
-- to datafile copies with the desired status. For example, only available
-- datafile copies can be backed up, but unavailable copies can be made
-- available. Deleted copies are never returned.
-- The duplicates parameter controls whether getDataFileCopy returns all
-- datafile copies or just the most recent (highest checkpoint scn) copy
-- of each datafile (file#).
-- Input parameters:
--   cdf_key
--     key of the datafile copy record in the recovery catalog
--   fname
--     name of the datafile copy to be translated.
--     The name must be a normalized filename
--   tag
--     tag of the datafile copies to be translated
--     The tag must be passed exactly as stored in the controlfile,
--     it is not uppercased by translate
--   available
--     if TRUE (1) return available datafile copies
--   unavailable
--     if TRUE (1) return unavailable datafile copies
--   duplicates
--     if TRUE (1) return all datafile copies
--     if FALSE (0) eliminate duplicate datafile copies
--
--    The remaining parameters are returned for deleteDataFileCopy
--
--    file#
--    fname
--    reset_scn
--    create_scn
--    ckp_scn
--    blocks_size
--
-- Exceptions:
--   NO_RECOVERY_CATALOG (ORA-20300)
--     translation by key is not supported without the recovery catalog
--   DATAFILE_COPY_DOES_NOT_EXIST
--     the specified key or filename does not match any datafile copy
--   DATAFILE_COPY_NAME_AMBIGUOUS
--     the specified filename matches more than one datafile copy
--   TAG_DOES_NOT_MATCH
--     the specified tag doesn't match any datafile copies
--   TRANSLATION_IN_PROGRESS (ORA-20203)
--     the previous translation conversation is still in progess.
--     To terminate get all datafiles with getDataFileCopy.
--   TRANSLATION_NOT_IN_PROGRESS (ORA-20204)
--     getDataFileCopy was called with no translation in progress
PROCEDURE translateDataFileCopyKey(
   cdf_key      IN number
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,statusMask   IN binary_integer DEFAULT NULL); -- for compatability
-- Obsolete as of 8.1.6
PROCEDURE translateDataFileCopyKey(
   cdf_key      IN number
  ,available    IN number
  ,unavailable  IN number
  ,recid        OUT number
  ,stamp        OUT number
  ,file#        OUT number
  ,fname        OUT varchar2
  ,reset_scn    OUT number
  ,create_scn   OUT number
  ,ckp_scn      OUT number
  ,block_size   OUT number
  ,blocks       OUT number);
PROCEDURE translateDataFileCopyName(
   fname        IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL); -- for compatability);
PROCEDURE translateDataFileCopyTag(
   tag          IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL); -- for compatability);
PROCEDURE translateDataFileCopyFno(
   fno          IN number
  ,available    IN number         DEFAULT NULL
  ,unavailable  IN number         DEFAULT NULL
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL);
-- Obsolete as of 8.1.6
PROCEDURE getDataFileCopy(
   recid        OUT number
  ,stamp        OUT number
  ,file#        OUT number
  ,fname        OUT varchar2
  ,reset_scn    OUT number
  ,create_scn   OUT number
  ,ckp_scn      OUT number
  ,block_size   OUT number
  ,blocks       OUT number);
----------------------------
-- Proxy Copy Translation --
----------------------------
PROCEDURE getProxyCopy(
   rcvRec       OUT rcvRec_t
  ,closeCursor  IN  boolean DEFAULT FALSE);
PROCEDURE translateProxyCopyKey(
   pc_key       IN number
  ,deviceType   IN varchar2
  ,available    IN number           DEFAULT NULL   -- for compatability
  ,unavailable  IN number           DEFAULT NULL   -- for compatability
  ,deleted      IN number           DEFAULT NULL   -- for compatability
  ,expired      IN number           DEFAULT NULL   -- for compatability
  ,statusMask   IN binary_integer   DEFAULT NULL); -- for compatability
-- Obsolete as of 8.1.6
PROCEDURE translateProxyCopyKey(
   pc_key       IN number
  ,device_type  IN varchar2
  ,available    IN number
  ,unavailable  IN number
  ,deleted      IN number
  ,recid        OUT number
  ,stamp        OUT number
  ,handle       OUT varchar2);
PROCEDURE translateProxyCopyHandle(
   handle       IN varchar2
  ,deviceType   IN varchar2
  ,available    IN number           DEFAULT NULL   -- for compatability
  ,unavailable  IN number           DEFAULT NULL   -- for compatability
  ,deleted      IN number           DEFAULT NULL   -- for compatability
  ,expired      IN number           DEFAULT NULL   -- for compatability
  ,statusMask   IN binary_integer   DEFAULT NULL); -- for compatability
-- Obsolete as of 8.1.6
PROCEDURE translateProxyCopyHandle(
   handle       IN varchar2
  ,device_type  IN varchar2
  ,available    IN number
  ,unavailable  IN number
  ,deleted      IN number
  ,recid        OUT number
  ,stamp        OUT number);
PROCEDURE translateProxyCopyTag(
   tag          IN varchar2
  ,device_type  IN varchar2
  ,available    IN number           DEFAULT NULL   -- for compatability
  ,unavailable  IN number           DEFAULT NULL   -- for compatability
  ,deleted      IN number           DEFAULT NULL   -- for compatability
  ,statusMask   IN binary_integer   DEFAULT NULL); -- for compatability
-- translateProxyCopyKey translates a proxy copy key to a
-- recid and stamp in V$PROXY_DATAFILE/V$PROXY_ARCHIVEDLOG
-- translateProxyCopyHandle translates handle and device type to a
-- proxy copy recid and stamp.
-- getProxyCopy returns one proxy copy after calling translateProxyCopyTag.
-- keep calling getProxyCopy until recid is null.
-- The available and unavailable parameters are used to limit the
-- translation to backup pieces with the desired status.
-- Input parameters:
--    pc_key
--      key of the proxy copy record in the recovery catalog
--    handle
--      proxy copy handle
--    device type
--      device type on which the proxy copy resides
-- Output parameters:
--    recid
--      recid/stamp of the proxy copy record (in V$PROXY_DATAFILE or
--                                               V$PROXY_ARCHIVEDLOG)
-- Exceptions:
--   NO_RECOVERY_CATALOG (ORA-20300)
--     this operation is not supported without the recovery catalog
--   PROXY_COPY_DOES_NOT_EXIST
--     the key does not match any proxy copy
--   PROXY_COPY_HANDLE_IS_AMBIGUOUS
--     the key matches more than one proxy copy
-- Obsolete as of 8.1.6
PROCEDURE getProxyCopy(
   recid OUT number
  ,stamp OUT number
  ,handle OUT varchar2);
------------------------------
-- Backup Piece Translation --
------------------------------
PROCEDURE getBackupPiece(
   bpRec        OUT bpRec_t
  ,closeCursor  IN  boolean DEFAULT FALSE);
PROCEDURE translateBackupPieceKey(
   key         IN  number
  ,available   IN  number            DEFAULT TRUE#
  ,unavailable IN  number            DEFAULT TRUE#
  ,expired     IN  number            DEFAULT TRUE#
  ,statusMask  IN  binary_integer    DEFAULT NULL);   -- for compatability
PROCEDURE translateBackupPieceKey(                        -- only used in 8.1.6
   bp_key          IN  number
  ,available    IN  number
  ,unavailable IN  number
  ,recid           OUT number
  ,stamp           OUT number
  ,handle       OUT varchar2
  ,set_stamp    OUT number
  ,set_count    OUT number
  ,piece#          OUT number);
PROCEDURE translateBackupPieceHandle(
   handle      IN  varchar2
  ,deviceType  IN  varchar2
  ,available   IN  number            DEFAULT NULL     -- for compatability
  ,unavailable IN  number            DEFAULT NULL     -- for compatability
  ,expired     IN  number            DEFAULT NULL     -- for compatability
  ,statusMask  IN  binary_integer    DEFAULT NULL);   -- for compatability
PROCEDURE translateBackupPieceHandle(                     -- only used in 8.1.6
   handle          IN  varchar2
  ,device_type IN  varchar2
  ,available    IN  number
  ,unavailable IN  number
  ,recid           OUT number
  ,stamp           OUT number
  ,set_stamp    OUT number
  ,set_count    OUT number
  ,piece#          OUT number);
PROCEDURE translateBackupPieceTag(
   tag          IN varchar2
  ,available    IN number             DEFAULT NULL     -- for compatability
  ,unavailable  IN number             DEFAULT NULL     -- for compatability
  ,statusMask   IN binary_integer     DEFAULT NULL);   -- for compatability
PROCEDURE translateBackupPieceBSKey(
   key          IN number
  ,tag          IN varchar2           DEFAULT NULL
  ,deviceType   IN varchar2           DEFAULT NULL
  ,pieceCount   IN number
  ,duplicates   IN number             DEFAULT TRUE#
  ,copyNumber   IN number             DEFAULT NULL
  ,available    IN number             DEFAULT TRUE#
  ,unavailable  IN number             DEFAULT FALSE#
  ,deleted      IN number             DEFAULT FALSE#
  ,expired      IN number             DEFAULT FALSE#
  ,statusMask   IN binary_integer     DEFAULT NULL);   -- for compatability
-- Obsolete as of 8.1.6
PROCEDURE translateBackupSetKey(
   bs_key          IN  number
  ,device_type     IN  varchar2
  ,available       IN  number
  ,unavailable     IN  number
  ,deleted         IN  number
  ,duplicates      IN  number
  ,backup_type     OUT varchar2
  ,recid           OUT number
  ,stamp           OUT number
  ,set_stamp       OUT number
  ,set_count       OUT number
  ,bslevel         OUT number
  ,completion_time OUT date);
-- Obsolete as of 8.1
PROCEDURE translateBackupSetKey(
   bs_key      IN  number
  ,device_type IN  varchar2
  ,available   IN  number
  ,unavailable IN  number
  ,deleted     IN  number
  ,duplicates  IN  number
  ,backup_type OUT varchar2
  ,recid       OUT number
  ,stamp       OUT number);
-- Obsolete as of 8.1.6
PROCEDURE translateBackupSetRecid(
   recid       IN  number
  ,stamp       IN  number
  ,device_type IN  varchar2
  ,bs_key      OUT number
  ,bslevel     OUT number
  ,completed   OUT date);
-- Obsolete as of 8.1
PROCEDURE translateBackupSetRecid(
   recid       IN  number
  ,stamp       IN  number
  ,device_type IN  varchar2);
-- translateBackupPieceBSKey translates the specified backup set into a list of
-- backup pieces.  If there are multiple available copies of a piece then
-- only the latest (with highest stamp) is returned.  If there is no available
-- copy of a piece then raise an exception.
-- Input parameters:
--    key
--      key of the backup set record in the recovery catalog
--    recid
--      recid of the backup set record (in V$BACKUP_SET)
--    stamp
--      stamp of the backup set record (in V$BACKUP_SET)
-- Output parameters:
--   device_type
--     type of the device on which the piece resides
--   handle
--     handle to the backup piece
-- Exceptions:
--   BACKUP_SET_MISSING
--     no backup set with the specified recid and stamp found
--   NO_RECOVERY_CATALOG (ORA-20300)
--     translation by bs_key is not supported without the recovery catalog
-- Obsolete as of 8.1.6
PROCEDURE getBackupPiece(
   recid      OUT number
  ,stamp      OUT number
  ,bpkey      OUT number
  ,set_stamp  OUT number
  ,set_count  OUT number
  ,piece#     OUT number
  ,copy#      OUT number
  ,status     OUT varchar2
  ,completion OUT date
  ,handle     OUT varchar2);
-- Obsolete as of 8.1
PROCEDURE getBackupPiece(
   recid      OUT number
  ,stamp      OUT number
  ,set_stamp  OUT number
  ,set_count  OUT number
  ,piece#     OUT number
  ,handle     OUT varchar2);
----------------------------
-- Backup Set Translation --
----------------------------
PROCEDURE translateBackupSetKey(
   key        IN  number
  ,bsRec      OUT bsRec_t);
PROCEDURE translateAllBackupSet(
   backupType            IN  binary_integer
  ,tag                   IN  varchar2
  ,statusMask            IN  binary_integer
  ,completedAfter        IN  date
  ,completedBefore       IN  date);
PROCEDURE getAllBackupSet(
   rcvRec OUT rcvRec_t);
------------------------
-- Controlfile Backup --
------------------------
-- getControlfileBackup is not a public function, but needs to be here due
-- to bug 1269570.
FUNCTION getControlfileBackup(
   rcvRec     OUT rcvRec_t)
RETURN number;
-- findControlFileBackup finds the optimal copy or backup of the controlfile
-- based on the given criteria.
-- The optimal copy is the one with highest checkpoint SCN.  Returns one of:
-- SUCCESS, AVAILABLE, UNAVAILABLE.
-- This is for 8.0.4 thru 8.1.5 compatibility
FUNCTION findControlFileBackup(
   type         OUT number
  ,recid        OUT number
  ,stamp        OUT number
  ,fname        OUT varchar2
  ,device_type  OUT varchar2
  ,ckp_scn      OUT number)
RETURN number;
-- Obsolete as of 8.1.6 (8.1.5 uses this)
FUNCTION findControlFileBackup(
   type         OUT number
  ,recid        OUT number
  ,stamp        OUT number
  ,fname        OUT varchar2
  ,device_type  OUT varchar2
  ,ckp_scn      OUT number
  ,rlg_scn      OUT number
  ,blksize      OUT number)
RETURN number;
-------------------------
-- Archived Log Backup --
-------------------------
PROCEDURE findArchivedLogBackup(
   thread    IN number
  ,sequence  IN number
  ,lowSCN    IN number);
-- findArchivedLogBackup finds a backup set containing the given archived log.
-- getArchivedLogBackup returns the record for the backup set.  The return
-- value is one of:  SUCCESS, AVAILABLE, UNAVAILABLE.
--
-- Input Parameter:
--    thread#
--    sequence#
--    low_scn
FUNCTION getArchivedLogBackup(
   rcvRec       OUT rcvRec_t)
RETURN binary_integer;
-- Obsolete as of 8.1.6
FUNCTION findArchivedLogBackup(
   thread#    IN  number
  ,sequence#  IN  number
  ,low_scn    IN  number
  ,type       OUT number
  ,recid      OUT number
  ,stamp      OUT number
  ,device_type OUT varchar2)
RETURN number;
-------------------
-- SPFILE Backup --
-------------------
FUNCTION getSpfileBackup(
   rcvRec       OUT rcvRec_t)
RETURN number;
---------------
-- List Copy --
---------------
PROCEDURE listTranslateControlfileCopy(
   tag             IN  varchar2
  ,completedAfter  IN  date
  ,completedBefore IN  date
  ,statusMask      IN  binary_integer   DEFAULT
                       BSavailable+BSunavailable+BSexpired); -- default for 8.1
PROCEDURE listGetControlfileCopy(
   rcvRec OUT rcvRec_t);
-- Obsolete as of 8.1.6
FUNCTION listGetControlfileCopy(
   bcfkey     OUT number
  ,ckpscn     OUT number
  ,ckptime    OUT date
  ,status     OUT varchar2
  ,completion OUT date
  ,fname      OUT varchar2)
RETURN number;
PROCEDURE listTranslateDataFileCopy(
   file#             IN number
  ,creation_change#  IN number
  ,tag               IN varchar2        DEFAULT NULL
  ,file_name_pattern IN varchar2        DEFAULT NULL
  ,completedAfter    IN date            DEFAULT NULL
  ,completedBefore   IN date            DEFAULT NULL
  ,statusMask        IN binary_integer  DEFAULT BSavailable+BSunavailable);
                                                             -- default for 8.1
PROCEDURE listGetDataFileCopy(
   rcvRec OUT rcvRec_t);
-- Obsolete as of 8.1.6
FUNCTION listGetDataFileCopy(
   cdf_key            OUT number
  ,status             OUT varchar2
  ,fname              OUT varchar2
  ,completion_time    OUT date
  ,checkpoint_change# OUT number
  ,checkpoint_time    OUT date)
RETURN number;
PROCEDURE listTranslateArchivedLogCopy(
   thread#           IN number
  ,sequence#         IN number
  ,first_change#     IN number
  ,file_name_pattern IN varchar2        DEFAULT NULL
  ,completedAfter    IN date            DEFAULT NULL
  ,completedBefore   IN date            DEFAULT NULL
  ,statusMask        IN binary_integer  DEFAULT
                       BSavailable+BSunavailable+BSexpired  -- 8.0/8.1 defaults
  ,needstby          IN number          DEFAULT NULL);
PROCEDURE listGetArchivedLogCopy(
   rcvRec       OUT rcvRec_t);
-- Obsolete as of 8.1.6
FUNCTION listGetArchivedLogCopy(
   al_key          OUT number
  ,status          OUT varchar2
  ,fname           OUT varchar2
  ,completion_time OUT date)
RETURN number;
-----------------
-- List Backup --
-----------------
PROCEDURE listTranslateControlfileBackup(
   tag             IN  varchar2
  ,completedAfter  IN  date
  ,completedBefore IN  date
  ,statusMask      IN  binary_integer   DEFAULT
                      BSavailable+BSunavailable+BSexpired   -- 8.0/8.1 defaults
  ,autobackup      IN  binary_integer    DEFAULT BScfile_all);
PROCEDURE listGetControlfileBackup(
   rcvRec OUT rcvRec_t);
-- Obsolete as of 8.1.6
FUNCTION listGetControlfileBackup(
   bskey      OUT number,
   ckpscn     OUT number,
   ckptime    OUT date)
RETURN number;
PROCEDURE listTranslateSpfileBackup(
   completedAfter  IN  date
  ,completedBefore IN  date);
PROCEDURE listGetSpfileBackup(
   rcvRec OUT rcvRec_t);
PROCEDURE listTranslateDataFileBackup(
   file#             IN number
  ,creation_change#  IN number
  ,tag               IN varchar2        DEFAULT NULL
  ,completedAfter    IN date            DEFAULT NULL
  ,completedBefore   IN date            DEFAULT NULL
  ,statusMask        IN binary_integer  DEFAULT
                      BSavailable+BSunavailable+BSexpired); -- 8.0/8.1 defaults
PROCEDURE listGetDataFileBackup(
   rcvRec OUT rcvRec_t);
-- Obsolete as of 8.1.6
FUNCTION listGetDataFileBackup(
   bs_key             OUT number
  ,backup_type        OUT varchar2
  ,incremental_level  OUT number
  ,completion_time    OUT date
  ,checkpoint_change# OUT number
  ,checkpoint_time    OUT date)
RETURN number;
-- 8.1.5 LIST implementation
PROCEDURE translateBackupFile(
   bs_recid    IN  number
  ,bs_stamp    IN  number
  ,fno         IN  number
  ,bskey       OUT number
  ,inclevel    OUT number
  ,backup_type OUT varchar2
  ,completed   OUT date);
-- Used by 8.0 and 8.1.6, but not 8.1.5
PROCEDURE listTranslateArchivedLogBackup(
   thread#           IN number
  ,sequence#         IN number
  ,first_change#     IN number
  ,completedAfter    IN date           DEFAULT NULL
  ,completedBefore   IN date           DEFAULT NULL
  ,statusMask        IN binary_integer DEFAULT
                      BSavailable+BSunavailable+BSexpired); -- 8.0/8.1 defaults
PROCEDURE listGetArchivedLogBackup(
   rcvRec OUT rcvRec_t);
-- Obsolete as of 8.1
FUNCTION listGetArchivedLogBackup(
   bs_key          OUT number
  ,completion_time OUT date)
RETURN number;
-- Obsolete as of 8.1.6, but used in 9.0
PROCEDURE listTranslateArchivedLogBackup(
   thread#      IN number   DEFAULT NULL
  ,lowseq       IN number   DEFAULT NULL
  ,highseq      IN number   DEFAULT NULL
  ,lowscn       IN number   DEFAULT NULL
  ,highscn      IN number   DEFAULT NULL
  ,from_time    IN date     DEFAULT NULL
  ,until_time   IN date     DEFAULT NULL
  ,pattern      IN varchar2 DEFAULT NULL);
-- Obsolete as of 8.1.6
FUNCTION listGetArchivedLogBackup(
   bs_key          OUT number
  ,thread#         OUT number
  ,sequence#       OUT number
  ,first_change#   OUT number
  ,next_change#    OUT number
  ,first_time      OUT date
  ,next_time       OUT date)
RETURN number;
--------------------
-- List Backupset --
--------------------
PROCEDURE listTranslateBackupsetFiles(
   bs_key          IN  number);
PROCEDURE listGetBackupsetFiles(
   rcvRec          OUT rcvRec_t);
---------------------
-- List Proxy Copy --
---------------------
-- Note that this is used for both datafiles and the controlfile
PROCEDURE listTranslateProxyDataFile(
   file#             IN number
  ,creation_change#  IN number
  ,tag               IN varchar2        DEFAULT NULL
  ,handle_pattern    IN varchar2        DEFAULT NULL
  ,completedAfter    IN date            DEFAULT NULL
  ,completedBefore   IN date            DEFAULT NULL
  ,statusMask        IN binary_integer  DEFAULT
                       BSavailable+BSunavailable+BSexpired); -- default for 8.1
PROCEDURE listGetProxyDataFile(
   rcvRec OUT rcvRec_t);
-- Obsolete as of 8.1.6
FUNCTION listGetProxyDataFile(
   xdf_key            OUT number
  ,recid              OUT number
  ,stamp              OUT number
  ,status             OUT varchar2
  ,handle             OUT varchar2
  ,completion_time    OUT date
  ,checkpoint_change# OUT number
  ,checkpoint_time    OUT date)
RETURN number;
-- This procedure serves absolutely no purpose.  It is here only for
-- backwards compatbility with 8.1.5.  The only call to this is from
-- krmkafs(), which gets called from krmkgra().  Since the calls are always
-- in sequence, we can simply save the last record returned from
-- getRecoveryAction and avoid doing an extra query.
-- The only value this functions returns that krmkgra() didn't already have
-- in 8.1.5 is the xdf_key.  Completion time was being estimated from the
-- stamp.
PROCEDURE listTranslateProxyDFRecid(
   recid              IN number
  ,stamp              IN number
  ,xdf_key            OUT number
  ,file#              OUT number
  ,status             OUT varchar2
  ,handle             OUT varchar2
  ,completion_time    OUT date
  ,checkpoint_change# OUT number
  ,checkpoint_time    OUT date);
-------------------------------
-- List Database Incarnation --
-------------------------------
PROCEDURE listTranslateDBIncarnation(
   db_name      IN varchar2 DEFAULT NULL);
FUNCTION listGetDBIncarnation(
   db_key            OUT number
  ,dbinc_key         OUT number
  ,db_name           OUT varchar2
  ,db_id             OUT number
  ,current_inc       OUT varchar2
  ,resetlogs_change# OUT number
  ,resetlogs_time    OUT date)
RETURN number;
--------------------------------------
-- List Rollback Segment Tablespace --
--------------------------------------
PROCEDURE listRollbackSegTableSpace;
FUNCTION listGetTableSpace(
   ts#               OUT number
  ,ts_name           OUT varchar2)
RETURN number;
------------------------
-- Incremental Backup --
------------------------
-- getIncrementalScn returns the starting scn for an incremental backup.
-- Input Parameters:
--   file#
--     datafile number
--   reset_scn
--     the resetlogs SCN of the datafile
--   reset_time
--     the resetlogs time of the datafile
--   incr_scn
--     level of the incremental backup
--   cumulative
--      TRUE# if the backup is cumulative
--   first
--      TRUE open the cursor, otherwise just fetch from already opened cursor
-- Exceptions
--   DATAFILE_DOES_NOT_EXIST
--   INVALID_LEVEL
--   NO_PARENT_BACKUP_FOUND
FUNCTION getIncrementalScn(
   file#        IN number
  ,create_scn   IN number
  ,reset_scn    IN number
  ,reset_time   IN date
  ,incr_level   IN number
  ,cumulative   IN number)
RETURN number;
-- This one is an improved version of above. If you want to get
-- incremental scn for all datafiles by opening the cursor only once, then
-- using this will give enormous performance improvement.
--
-- NOTE!! NOTE!! NOTE!!
-- If you pass NULL to file# then it means all of the following
--  o all datafiles
--  o datafiles which has reset_scn and reset_time of current incarnation.
-- It is the callers responsibility to fetch the incremental scn of remaining
-- datafiles which doesn't have reset_scn and reset_time of current
-- incarnation.
PROCEDURE getIncrementalScn(
   first        IN  boolean                  -- open the cursor if this is TRUE
  ,file#        IN  number
  ,create_scn   IN  number
  ,reset_scn    IN  number
  ,reset_time   IN  date
  ,incr_level   IN  number
  ,cumulative   IN  number
  ,rcvRec       OUT rcvRec_t);
--------------------
-- Offline Ranges --
--------------------
PROCEDURE findOfflineRangeCopy(
   offr_recid   IN number
  ,offr_ckpscn  IN number
  ,cf_cretime   IN date
  ,dbinc_key    IN number);
PROCEDURE getOfflineRangeCopy(
   rcvRec       OUT     rcvRec_t);
-- Obsolete as of 8.1.6
FUNCTION getOfflineRangeCopy
RETURN varchar2;
-- findOfflineRangeCopy begins the search for a controlfile copy
-- containing a specified offline range.  getOfflinRangeCopy is called
-- to retrieve the controlfile names one by one.  NULL is returned at
-- end of fetch.
-- Input Parameters:
--   offr_recid
--     recid of offline range
--   offr_ckpscn
--     online checkpoint SCN (end) of offline range
--   dbinc_rlgscn
--     resetlogs SCN of the db incarnation that contains this range
-- Output Parameters:
--   offr_recid
--     recid of the offline range record
--   offr_stamp
--     stamp of the offline range record
--   type
--     type of the controlfile that contains the offline range.
--     COPY or BACKUP
--   recid
--     the recid of datafile copy record or
--     the recid of the backup set record
--   stamp
--     The timestamp associated with the recid in the controlfile.
--   fname
--     filename of the controlfile copy
--     NULL if a backup controlfile is returned
-- returns TRUE (1) if a copy or backup was found
-- returns FALSE (0) if no copy or backup was found
-- Exceptions:
--   OFFLINE_RANGE_NOT_FOUND (ORA-20250)
--     No offline range was found for the datafile starting at the offline SCN
---------------------------------------
-- Recovery Functions and Procedures --
---------------------------------------
PROCEDURE setComputeRecoveryActionMasks(
   containerMask        IN number
  ,actionMask           IN number
  ,allRecords           IN number
  ,availableMask        IN binary_integer);
--Obsolete as of 8.1.7
PROCEDURE setComputeRecoveryActionMasks(
   containerMask        IN number
  ,actionMask           IN number
  ,allRecords           IN number);
-- Obsolete as of 8.1.6
PROCEDURE setRAflags(
   kindMask    IN number
  ,allRecords  IN boolean);
FUNCTION computeRecoveryActions(
fno        IN number,   -- Datafile number.
crescn     IN number,   -- Datafile creation SCN.
df_rlgscn  IN number    -- Datafile resetlogs SCN.  Null if this is a RESTORE
   default null,        -- command, else this is the value in the datafile
                        -- header for the datafile we are RECOVERing.
df_rlgtime IN date      -- Datafile resetlogs time.  Null if df_rlgscn is
   default null,        -- null, else value from datafile header.
df_ckpscn  IN number    -- Datafile checkpoint SCN.  Null if df_rlgscn is
   default null,        -- null, else value from datafile header.
offlscn    IN number    -- kccfeofs (may be null).
   default 0,
onlscn     IN number    -- kccfeonc (null if offlscn is null).
   default 0,
onltime    IN date      -- kccfeonc_time
   default null,
cleanscn   IN number    -- kccfecps if either SOR or WCC set, else null.
   default 0,
clean2scn  IN number    -- CF ckpt SCN if WCC set, infinity if SOR bit set
   default 0,           -- else null.
clean2time IN date      -- cf ckpt time if WCC, SYSDATE if SOR
   default null,
allowfuzzy IN boolean   -- TRUE if can be fuzzy at until SCN/time, FALSE if
  default FALSE,        -- not.  default is FALSE.
partial_rcv IN boolean  -- TRUE if can do partial recovery, FALSE if not
  default FALSE,
cf_scn     IN number    -- controlfile checkpoint SCN (NULL if none mounted)
  default NULL,
cf_cretime IN date      -- controlfile creation time (NULL if none mounted)
  default NULL,
cf_offrrid IN number    -- recid of oldest offline range in controlfile
  default NULL,         -- (NULL if none mounted)
allCopies  IN boolean   -- if TRUE, then stack all valid copies of a bu set
  default FALSE
) return binary_integer;
-- Returns:
--   SUCCESS -> the file can be restored/recovered.
--   else one of RESTORABLE, AVAILABLE, UNAVAILABLE, NO_ACTION.
-- computeRecoveryActions return values --
SUCCESS     CONSTANT binary_integer := 0;
UNAVAILABLE CONSTANT binary_integer := 1;
AVAILABLE   CONSTANT binary_integer := 2;
RESTORABLE  CONSTANT binary_integer := 3;
NO_ACTION   CONSTANT binary_integer := 4;
-- SUCCESS:      A file has been found for RESTORE, or the file on disk
--               can be recovered.
-- UNAVAILABLE:  If RESTORE, then no datafilecopy or level 0 backup was found.
--               If RECOVER, then some incremental backup is missing, or the
--               datafile on disk is too old to recover.
-- AVAILABLE:    If RESTORE, then some level 0 or datafilecopy exists, but
--               the required device type is not allocated.
-- RESTORABLE:   This is returned only when doing a RECOVER.  It means that
--               the file on disk cannot be recovered, but there is some level
--               0 or datafilecopy that could be restored and then recovered.
-- NO_ACTION:    There are no incrementals or offline ranges to apply, but
--               the file should be recoverable with redo.  No guarantee is
--               made that the logs needed are actually available.
FUNCTION getRecoveryAction(
   action OUT rcvRec_t)
RETURN binary_integer;
-- Obsolete as of 8.1.6
FUNCTION getRecoveryAction(
   kind       OUT number
  ,set_stamp  OUT number
  ,set_count  OUT number
  ,recid      OUT number
  ,stamp      OUT number
  ,fname      OUT varchar2
  ,blocksize  OUT number
  ,blocks     OUT number
  ,devtype    OUT varchar2
  ,from_scn   OUT number
  ,to_scn     OUT number
  ,to_time    OUT date
  ,rlgscn     OUT number
  ,rlgtime    OUT date
  ,cfcretime  OUT date
  ,dbinc_key  OUT number)
RETURN binary_integer;
PROCEDURE printRecoveryActions;
PROCEDURE trimRecoveryActions(
   maxActions           IN number
  ,containerMask        IN number
  ,actionMask           IN number);
-- trimRecoveryActions will trim the stack down to the specified number
-- actions if it contains more.  This is used by report obsolete to implement
-- the redundancy count.  The reason for it is that getRecoveryActions
-- returns actions in LIFO order.  This means the oldest actions, which
-- were stacked most recently, are returned first.  However, report obsolete
-- wants to keep only the most recent backups when constructing the
-- "must keep" list.  We solve the problem by getting rid of any excess
-- actions first, and so the order in which getRecoveryActions returns them
-- won't matter.  Note that only actions whose type_con and type_act are
-- selected by the masks will be deleted.  Other actions are left on the
-- stack.
---------------------
-- Report Obsolete --
---------------------
PROCEDURE reportTranslateDFDel ;
-- pre 8.1.5 version
FUNCTION reportGetDFDel(
   file#               OUT number
  ,filetype            OUT number
  ,checkpoint_change#  OUT number
  ,checkpoint_time     OUT date
  ,resetlogs_change#   OUT number
  ,resetlogs_time      OUT date
  ,incremental_change# OUT number
  ,fuzzy_change#       OUT number
  ,recid               OUT number
  ,stamp               OUT number
  ,fname               OUT varchar2
  ,restorable          OUT number)
RETURN number;
-- 8.1.5+ version
FUNCTION reportGetDFDel(
   file#               OUT number
  ,filetype            OUT number
  ,checkpoint_change#  OUT number
  ,checkpoint_time     OUT date
  ,resetlogs_change#   OUT number
  ,resetlogs_time      OUT date
  ,incremental_change# OUT number
  ,fuzzy_change#       OUT number
  ,recid               OUT number
  ,stamp               OUT number
  ,fname               OUT varchar2
  ,restorable          OUT number
  ,key                 OUT number
  ,completion_time     OUT date)
RETURN number;
------------
-- TSPITR --
------------
FUNCTION getCloneName(
   fno IN number
  ,crescn IN number)
RETURN varchar2;
---------------
-- DUPLICATE --
---------------
FUNCTION wasFileOffline(
   fno    IN number
  ,untilscn IN number)
RETURN number;
-------------------------
-- RMAN Configuration ---
-------------------------
PROCEDURE getConfig(
   conf#          OUT    number
  ,name           IN OUT varchar2
  ,value          IN OUT varchar2
  ,first          IN     boolean);
------------------------------
-- Get max(copy#) --
------------------------------
FUNCTION getmaxcopyno(
   bsstamp         IN    number
  ,bscount         IN    number)
RETURN number;
--------------------------
-- Add Corruption Table --
--------------------------
PROCEDURE bmrAddCorruptTable(
   dfnumber    OUT number
  ,blknumber   OUT number
  ,range       OUT number
  ,first       IN  boolean);
------------------------
-- Get Backup History --
------------------------
PROCEDURE getDfBackupHistory(
   backedUpDev     IN   varchar2
  ,first           IN   boolean
  ,file#           IN   number  DEFAULT NULL
  ,crescn          IN   number  DEFAULT NULL
  ,reset_scn       IN   number  DEFAULT NULL
  ,reset_time      IN   date    DEFAULT NULL
  ,bhistoryRec     OUT  bhistoryRec_t);
PROCEDURE getAlBackupHistory(
   backedUpDev     IN   varchar2
  ,first           IN   boolean
  ,thread#         IN   number  DEFAULT NULL
  ,sequence#       IN   number  DEFAULT NULL
  ,bhistoryRec     OUT  bhistoryRec_t);
PROCEDURE getBsBackupHistory(
   backedUpDev     IN   varchar2
  ,first           IN   boolean
  ,set_stamp       IN   number  DEFAULT NULL
  ,set_count       IN   number  DEFAULT NULL
  ,bhistoryRec     OUT  bhistoryRec_t);
-- Obsolute as of 9.0.1
PROCEDURE getBackupHistory(
   dfRec            IN  dfRec_t
  ,backedUpDev      IN  varchar2
  ,nbackupsFlag     IN  number
  ,bscompletionFlag IN  number
  ,nbackups         OUT number
  ,bscompletion     OUT date);
-- Obsolute as of 9.0.1
PROCEDURE getBackupHistory(
   alRec            IN  alRec_t
  ,backedUpDev      IN  varchar2
  ,nbackupsFlag     IN  number
  ,bscompletionFlag IN  number
  ,nbackups         OUT number
  ,bscompletion     OUT date);
-- Obsolute as of 9.0.1
PROCEDURE getBackupHistory(
   bpRec            IN  bpRec_t
  ,backedUpDev      IN  varchar2
  ,nbackupsFlag     IN  number
  ,bscompletionFlag IN  number
  ,nbackups         OUT number
  ,bscompletion     OUT date);
------------------
-- Version Info --
------------------
FUNCTION getPackageVersion
RETURN varchar2;
FUNCTION isStatusMatch(status      IN VARCHAR2,
                       mask        IN NUMBER) RETURN NUMBER;
FUNCTION isDeviceTypeAllocated(deviceType IN varchar2)
                      RETURN NUMBER;
FUNCTION isBackupTypeMatch(btype       IN VARCHAR2,
                           mask        IN binary_integer)
                                              RETURN NUMBER;
pragma TIMESTAMP('2000-03-12:13:51:00');
END; -- dbms_rcvman or x$dbms_rcvman
-- CUT_HERE    <- tell sed where to chop off the rest

CREATE OR REPLACE PACKAGE BODY "RMAN"."DBMS_RCVMAN" IS
-- prvtrmnu.sql
--
--  Copyright (c) Oracle Corporation 1995, 2001. All Rights Reserved.
--
--    NAME
--      prvtrmnu.sql - Recovery MANager package body
--
--    DESCRIPTION
--      This package contains procedures querying information that
--      Recovery Manager needs from the recovery catalog or the target
--      database control file
--
--      This is the version used by catrman.sql; there is a separate
--      body in the file prvtrmns.pls that is loaded into SYS; this one
--      is loaded into a user schema.
--
--    NOTES
--      Remember to make corresponding changes in prvtrmns.pls
--
--    MODIFIED   (MM/DD/YY)
--    molagapp    02/14/02 - ignore debug exception
--    molagapp    02/01/02 - cast null
--    sdizdar     02/01/02 - bug-2209822: add auxName to cursors
--    molagapp    01/24/02 - rework backup history cursors
--    molagapp    01/23/02 - bug-2174697: add inCorebsRec_t framework
--    molagapp    01/19/02 - listBackupsetFiles - obey allIncarnations flg
--    molagapp    12/12/01 - bug 2146724
--    molagapp    11/29/01 - update package version 9.2.0
--    sdizdar     11/05/01 - fix findBackupsetFiles
--    molagapp    10/19/01 - add cfSequence, cfDate to recovery record
--    molagapp    10/17/01 - bug 1530744
--    molagapp    10/19/01 - bug 2067187
--    molagapp    10/06/01 - add translateAllBackupSet
--    sdizdar     09/07/01 - SPFILE backup:
--                           - add getSpfileBackup(), listGetSpfileBackup(),
--                             listTranslateSpfileBackup(), findSpfileBackup_c
--    molagapp    09/18/01 - bug-1999761
--    molagapp    07/23/01 - bug-1900314
--    fsanchez    05/23/01 - dbnewid
--    sdizdar     06/15/01 - bug-1782808:
--                           - improve computerecoveryaction
--                           - fix resetAll and setTransClause
--    molagapp    06/07/01 - bug-1712720: add setTransClause
--    molagapp    05/06/01 - add cursors to fix backup history performance
--    swerthei    04/16/01 - improve performance of getCheckpoint
--    sdizdar     04/21/01 - bug-961713: fix computeUntilSCN
--    swerthei    04/04/01 - use new corruption view
--    molagapp    05/08/01 - fix query performance
--    sdizdar     04/10/01 - bug-1717268: add flags to getBackupHistory
--    swerthei    04/03/01 - add new flavor of getCheckpoint
--    swerthei    03/12/01 - simplify lrtbs query
--    fsanchez    01/25/01 - bug-1586048
--    sdizdar     11/10/00 - bug-1496982: 8.2.0 -> 9.0.0
--    sdizdar     11/25/00 - fixed findConfig_c
--    sdizdar     11/09/00 - bug-1478539: add keep attributes to findBackupSet
--    dbeusee     10/27/00 - bug-1469307
--    sdizdar     11/04/00 - bug-1479780:
--                          - findArchivedLogCopy doesn't return online logs
--    sdizdar     10/23/00 - bug-1477008:
--                           - add controlfile to openRecoveryActionCursor
--    sagrawal    10/24/00 - Fixing defaults for body and spec
--    dbeusee     10/17/00 - bug-1462384
--    sdizdar     10/08/00 - bug-1398333:
--                           - translate don't use rc_backup_set but bs
--    sdizdar     08/24/00 - trimRecoveryActions doesn't count "keep" backups
--                         - keep atributes added to right views
--    dbeusee     09/25/00 - rman82_list_fixes_1
--    molagapp    08/23/00 - add autobackup arg to listTranslateCfileBackup
--    molagapp    08/28/00 - fix 8.2 upgrade
--    dbeusee     06/13/00 - rman82_maint_syntax_unification
--    dbeusee     07/20/00 - rman82_debug_enhancements
--    sdizdar     08/13/00 - Show all and misc improvement:
--                          - change RECOVERABLE/UNERCOREVABLE to LOGS/NOLOGS
--    smuralid    08/08/00 - common sql fe changes
--    molagapp    07/19/00 - restore optimization.
--    sdizdar     06/29/00 - Configure auxfilename and exclude tablespace:
--                          - add tsNumber and inBackup in
--                            datafile translation
--    banand      06/23/00 - set duplicate in alRec_t
--    molagapp    06/08/00 - restartable backups
--    molagapp    06/01/00 - backup optimization
--    sdizdar     05/20/00 - RMAN Retention Policy (keep):
--                           - add keep attributes in translation procedures
--                           - modified setUntilTime
--                           - modified findArcLogBackup/Copy
--    swerthei    06/29/00 - fix cursor variables
--    mjstewar    07/24/00 - OMF: set newname ... to new
--    banand      05/19/00 - use name and value in findConfig_c
--    dbeusee     05/03/00 - rman82_cf_status_unification
--    dbeusee     11/01/99 - status_mask
--    molagapp    05/18/00 - block media recovery
--    fsanchez    03/24/00 - instantiate_standby
--    sdizdar     04/15/00 - RMAN configuration: add getConfig
--    molagapp    04/27/00 - backup backupset: add getmaxcopyno
--    banand      04/12/00 - add tag options to recover cmd
--    dbeusee     04/03/00 - xcheck_autolocate
--    swerthei    03/30/00 - xcheck_autolocate: return backup piece device type
--    fsanchez    01/07/00 - bug-1040149
--    molagapp    02/16/00 - bug 1186598: fix compatibility with RMAN 8.1.5
--                           executable
--    dbeusee     10/20/99 - bug-1043144: fix findProxyCopy
--    fsanchez    09/24/99 - fix findValidBackupSet_c cursor
--    mluong      08/30/99 - Fix typo
--    gpongrac    10/12/99 - remove validateBackupSetCursor_t
--    gpongrac    09/09/99 - comments
--    swerthei    08/05/99 - close cursors in resetAll
--    mluong      08/30/99 - fix typo
--    gpongrac    08/10/99 - fix translateArchivedLog
--    gpongrac    07/12/99 - bug 927353: translateArchivedLogSCNRange needs to
--    gpongrac    07/06/99 - change rcver to 8.1.6
--    gpongrac    06/16/99 - report obsolete support
--    gpongrac    01/12/99 - 8.2 restructure
--    gpongrac    04/08/99 - change REM to --
--    swerthei    12/28/98 - 787381 - consider proxies in getIncrementalSCN
--    swerthei    11/26/98 - more debugging improvements
--    swerthei    11/25/98 - enable debugging code from rman
--    gpongrac    11/25/98 - fix debugging in getRecveryAction0
--    dbeusee     11/13/98 - misc_815: Handle LIST RECOVERABLE UNTIL TIME...
--    dbeusee     11/11/98 - misc_815: fix LIST COPY LIKE...
--    dbeusee     11/07/98 - misc_815: fix LIST COPY/BS FROM TIME/UNTIL TIME..
--    dbeusee     10/30/98 - misc_815: added stamp2date for LIST COPY
--    dbeusee     10/19/98 - misc_815: fix LIST BACKUPSET FROM TIME...
--    gpongrac    10/19/98 - misc_815: fix LIST with TAG
--    dbeusee     10/17/98 - misc_815: fix LIST ALL device type filtering
--    gpongrac    10/05/98 - misc_815: fix recovery
--    gpongrac    09/10/98 - misc_815: fix computeRecoveryActions for list cmd
--    swerthei    10/24/98 - add proxy support to REPORT OBSOLETE
--    swerthei    10/20/98 - add listTranslateProxyDataFile, listGetProxyDataF
--    fsanchez    09/04/98 - bug719092
--    swerthei    06/22/98 - prepare for wrapping to recover.bsq
--    gpongrac    06/04/98 - fix comment
--    swerthei    06/01/98 - add CHANGE PROXY
--    swerthei    05/27/98 - proxy restore
--    dbeusee     05/15/98 - misc_81_fixes_1
--    fsanchez    05/12/98 - duplex_backup_set
--    dbeusee     04/21/98 - rpt_redundancy_enh
--    gpongrac    03/04/98 - fix getPackageVersion
--    dbeusee     04/06/98 - xcheck enh.
--    dbeusee     03/29/98 - Update comment about restore only (not true any m
--    fsanchez    03/25/98 - Duplexed backup sets
--    dbeusee     03/01/98 - list enh.
--    gpongrac    01/23/98 - upgrade catalog_version to 8.0.5
--    dbeusee     02/11/98 - Fix bug 613166.
--    fsanchez    01/04/98 - Allow setDatabase to receive dbid without dbname
--    gpongrac    12/23/97 - change findcontrolfilebackup
--    gpongrac    10/30/97 - bug 560638: fix validatebackupset
--    gpongrac    10/02/97 - allow <= in setuntiltime and dbq
--    gpongrac    09/03/97 - have dfcopy name xlate return filesize
--    tpystyne    09/11/97 - bug 480172, fix name translation
--    swerthei    08/29/97 - add getdatafile.read_only
--    swerthei    08/18/97 - add getdatafile.stop_change#
--    gpongrac    07/02/97 - change to version 8.0.4
--    gpongrac    07/01/97 - avoid offr records with stamp of 0
--    mzhou       08/07/97 - fix order by ts#
--    gpongrac    07/22/97 - chang lrtbs cursor to order by tsid so system ts
--    swerthei    04/23/97 - fix list backupset
--    gpongrac    04/22/97 - offline range can end at resetlogs scn
--    dalpern     04/16/97 - renamed as prvtrmnu, v. prvtrmns
--    gpongrac    04/11/97 - add cfscn to computeRecoveryActions
--    gpongrac    04/10/97 - add rlgtime to getRecoveryAction
--    gpongrac    04/10/97 - fix incarnation check at top of computeRecov...0
--    gpongrac    04/04/97 - add translateBackupPieceTag
--    gpongrac    04/04/97 - deal with controlfiles that have no offline range
--    gpongrac    04/01/97 - add offline range info to computeRecoveryActions
--    swerthei    03/27/97 - add getDataFile.ts_name
--    tpystyne    03/20/97 - update catalog version to 8.00.03
--    swerthei    03/21/97 - fix merge error
--    swerthei    03/12/97 - get file sizes in blocks, for metrics
--    gpongrac    03/17/97 - fix cursor to deal with inplicit offline ranges c
--    gpongrac    03/15/97 - add to_time for implicit offline ranges in comput
--    gpongrac    03/10/97 - remove df_ckpscn as arg to openRecoveryActionCurs
--    gpongrac    03/10/97 - add setDebugOn and setDebugOff
--    gpongrac    03/03/97 - verify df_rlgscn in computeRecoveryActions0
--    gpongrac    02/28/97 - check allocate device types in addAction
--    gpongrac    02/27/97 - only do partial recovery if have current controlf
--    gpongrac    02/26/97 - fix compile errors
--    gpongrac    02/26/97 - fix syntax errors
--    gpongrac    02/26/97 - add new recovery functions
--    gpongrac    02/20/97 - require offr.online_time be strictly less than un
--    gpongrac    02/20/97 - simplify handling of until time/scn in where clau
--    swerthei    01/21/97 - change parameters for translatebackupsetkey
--    swerthei    01/15/97 - add dumpState
--    gpongrac    01/14/97 - add getCloneName
--    tpystyne    12/17/96 - add listRollbackSegTableSpace
--    swerthei    01/08/97 - change parameters for backup piece translation
--    swerthei    01/06/97 - continue REPORT DELETABLE
--    gpongrac    01/06/97 - add nxtscn to getArchivedLog
--    swerthei    01/03/97 - add getParentIncarnation
-- ### comments from 1996 removed
---------------------------------------------
-- *** PACKAGE VARIABLES/TYPES SECTION *** --
---------------------------------------------
----------------------
-- Global Constants --
----------------------
MAXSCNVAL  CONSTANT number := 9e125; -- guaranteed higher than any SCN
MAXSEQVAL  CONSTANT number := 2**32-1;
MINDATEVAL CONSTANT date   := to_date('01/01/1900','MM/DD/YYYY');
MAXDATEVAL CONSTANT date   := to_date('12/31/9999','MM/DD/YYYY');
-- keep types (see definitions in krmi.h and rcv/if/kcc3.h)
KEEP_NO      CONSTANT number := 0;
KEEP_LOGS    CONSTANT number := 256;
KEEP_NOLOGS  CONSTANT number := 512;
KEEP_CONSIST CONSTANT number := 1024;
DEB_UNDEF  CONSTANT number := 0;
DEB_PRINT  CONSTANT number := 0;
DEB_ENTER  CONSTANT number := 1;
DEB_EXIT   CONSTANT number := 2;
DEB_IN     CONSTANT number := 3;
DEB_OPEN   CONSTANT number := 4;
DEB_DEF_PNAME CONSTANT varchar2(50) := 'prvtrmnu';
----------------------
-- Global Variables --
----------------------
this_db_key     number := NULL;
this_dbinc_key  number := NULL;
this_reset_scn  number := NULL;
this_reset_time date;
type pnames is table of varchar2(50) index by binary_integer;
pname_i         number :=0;
last_pnames     pnames;
debug           boolean := FALSE;
--------------------
-- rcvRec_t Stack --
--------------------
TYPE rcvRecTab_t IS TABLE OF rcvRec_t;          -- recovery record stack type
rcvRecStack rcvRecTab_t := rcvRecTab_t();       -- recovery record stack
-----------------------
-- getPackageVersion --
-----------------------
TYPE versionList_t IS TABLE OF varchar2(8) INDEX BY binary_integer;
versionList             versionList_t;
versionMaxIndex         binary_integer;
versionCounter          binary_integer;
-----------------
-- setDatabase --
-----------------
catalogVersion CONSTANT VARCHAR2(8) := '09.02.00';
-- For getParentIncarnation
getParentIncarnationKey number;
---------------------
-- Filtering Flags --
---------------------
allIncarnations number;                 -- allow records from non-current
                                        -- incarnation
ignoreCreationSCN number;               -- a stupid flag that is here
                                        -- only to provide behaviour that is
                                        -- backwards compatible with a kludge
                                        -- dbeusee put in to compensate for
                                        -- one of his bugs.
untilSCN        number;
untilTime       date;
restoreSource   number;
restoreTag      bp.tag%TYPE;
onlyStandby     number;
-------------------
-- setDeviceType --
-------------------
TYPE deviceList_t IS TABLE OF rc_backup_piece.device_type%TYPE
     INDEX BY binary_integer;
deviceList      deviceList_t;
deviceCount     number;
diskDevice      boolean;
anyDevice       boolean;
-----------------------------------------
-- In Memory Validate BackupSet Record --
-----------------------------------------
-- We have faced performance problems when calling validateBackupSet.
-- This record is introduced to resolve the performance issues. The idea
-- is to keep all validBackupSet in memory and its deviceType. For example,
-- if a backupset is created on X devices, then Y records will pushed into
-- the stack for that backupset, where Y is the number of devices on which
-- this backupset satisfies the requested statusMask.
--
-- This is a stripped version of bsRec_t because we want to keep minimum
-- information in memory to determine a backupset is valid or not.
--
-- NOTE!! NOTE!! NOTE!!
-- It is extremely IMPORTANT to limit the size of record because keeping
-- huge amount of these records in memory will lead to ORA-6500
-- PLSQL: storage error when you have around 10MB records.
--
-- This is not used in catalog and exists here only for testing purpose.
-- We derefed this change in catalog because we were hitting ORA-6500 error
-- for around 1MB of records without seeing much performance benefit.
TYPE inCorebsRec_t IS RECORD
(
   bsKey          number,
   setStamp       number(10),
   setCount       number(10),
   devindx        pls_integer,    -- index into the inCoredeviceList
   pieceCount     pls_integer
);
-----------------------
-- inCorebsRec Stack --
-----------------------
TYPE inCorebsRecTab_t IS TABLE OF inCorebsRec_t;  -- incorebs record stack type
inCorebsRecStack inCorebsRecTab_t := inCorebsRecTab_t();
-- This is present to save memory because duplicating deviceType in
-- all inCorebsRec_t is just waste of memory since each deviceType is
-- is 255 bytes.
inCoredeviceList     deviceList_t;
inCoredeviceCount    binary_integer := 0;   -- number of devices
-- for inCorebsRec_c  cursor
TYPE inCorebsCursor_t IS RECORD
(
   bsKey          number,
   setStamp       number(10),
   setCount       number(10),
   deviceType     rc_backup_piece.device_type%TYPE,
   pieceCount     pls_integer
);
----------------------------
-- computeRecoveryActions --
----------------------------
TYPE rcvRecCursor_t IS REF CURSOR return rcvRec_t;
TYPE rcvRecStackState_t IS RECORD
(
   lowAction number,                    -- action with lowest from_scn on
                                        -- rcvRecStack that is not a fullKind.
                                        -- Usually points to top of stack, but
                                        -- if computeRA_allRecords is TRUE,
                                        -- then may point down into stack.
   savePoint number,                    -- most recently added full_act_t
   top       number                     -- top of stack at start of a recursive
                                        -- test search of a possible parent
                                        -- incarnation
);
rcvRecStackState        rcvRecStackState_t;
computeRA_allRecords    number;         -- do not stop at first full backup and
                                        -- return all incremental backups
computeRA_restorable    boolean;        -- cannot recover the datafile we've
                                        -- requested to recover, but there
                                        -- is a backup that we could restore
                                        -- and recover.
computeRA_available     boolean;        -- there is a backup available on
                                        -- some non-allocated device type
computeRA_availableMask binary_integer;
-- computeRecoveryAction/addAction/addRedo return code values
action_OK                number := 0;
action_FAIL              number := 1;
action_SKIP              number := 2;
action_OLD_REDO          number := 3;
action_WRONG_INCARNATION number := 4;
old_redo exception;                     -- redo from old incarnation
pragma exception_init(old_redo, -20501);
-----------------------
-- getRecoveryAction --
-----------------------
getRA_containerMask     number;
getRA_actionMask        number;
getRA_likePattern       cdf.fname%TYPE;
getRA_completedAfter    date;
getRA_completedBefore   date;
------------------------
-- Translation Clause --
------------------------
tc_thread               number;
tc_fromTime             date;
tc_toTime               date;
tc_fromSCN              number;
tc_toSCN                number;
tc_fromSeq              number;
tc_toSeq                number;
tc_pattern              varchar2(512);
------------------------
-- Controlfile Backup --
------------------------
CURSOR findControlfileCopy(
   currentIncarnation   IN     number         DEFAULT TRUE#
  ,tag                  IN     varchar2       DEFAULT NULL
  ,pattern              IN     varchar2       DEFAULT NULL
  ,completedAfter       IN     date           DEFAULT NULL
  ,completedBefore      IN     date           DEFAULT NULL
  ,untilSCN             IN     number         DEFAULT NULL
  ,statusMask           IN     binary_integer
  ,needstby             IN     number         DEFAULT NULL)
RETURN rcvRec_t IS
   -- Replaces:  ccf_name, lccf
   SELECT imageCopy_con_t       type_con,
          ccf_key               key_con,
          ccf_recid             recid_con,
          ccf_stamp             stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_char(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          fname                 fileName_con,
          tag                   tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          to_number(null)       blocks_con,     -- ccf doesn't have blocks
          block_size            blockSize_con,
          'DISK'                deviceType_con,
          completion_time       compTime_con,
          create_time           cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          ccf.ckp_scn           toSCN_act,
          ccf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          ccf.dbinc_key         dbincKey_act,
          to_number(null)       level_act,
          0                     dfNumber_obj,
          0                     dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          ccf.keep_options      keep_options,
          ccf.keep_until        keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM ccf, dbinc
    WHERE dbinc.db_key = this_db_key            -- belongs to this database
      AND dbinc.dbinc_key = ccf.dbinc_key
      AND (findControlfileCopy.currentIncarnation = FALSE# OR
           this_dbinc_key = ccf.dbinc_key)
      AND (findControlfileCopy.tag is NULL OR
           findControlfileCopy.tag = tag)
      AND (findControlfileCopy.pattern is NULL OR
           fname LIKE findControlfileCopy.pattern)
      AND (findControlfileCopy.completedAfter is NULL OR
           completion_time >= findControlfileCopy.completedAfter)
      AND (findControlfileCopy.completedBefore is NULL OR
           completion_time <= findControlfileCopy.completedBefore)
      AND (findControlfileCopy.untilSCN is NULL OR
           ccf.ckp_scn <= findControlfileCopy.untilSCN)
      AND isStatusMatch(status,statusMask) = TRUE#
      AND (needstby is NULL OR
           nvl(controlfile_type,'B') = decode(needstby, TRUE#, 'S', 'B'))
    ORDER BY toSCN_act desc,            -- for finding best backup
             stamp_con desc;            -- for LIST and to get most recent
CURSOR findControlfileProxyCopy(
   currentIncarnation   IN     number         DEFAULT TRUE#
  ,tag                  IN     varchar2       DEFAULT NULL
  ,pattern              IN     varchar2       DEFAULT NULL
  ,completedAfter       IN     date           DEFAULT NULL
  ,completedBefore      IN     date           DEFAULT NULL
  ,untilSCN             IN     number         DEFAULT NULL
  ,statusMask           IN     binary_integer
  ,needstby             IN     number         DEFAULT NULL)
RETURN rcvRec_t IS
   -- Replaces: xcfq, lxdf
   SELECT proxyCopy_con_t       type_con,
          xcf_key               key_con,
          xcf_recid             recid_con,
          xcf_stamp             stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_char(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          handle                fileName_con,
          tag                   tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          to_number(null)       blocks_con,     -- xcf doesn't have blocks
          block_size            blockSize_con,
          device_type           deviceType_con,
          completion_time       compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          xcf.ckp_scn           toSCN_act,
          xcf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          xcf.dbinc_key         dbincKey_act,
          to_number(null)       level_act,
          0                     dfNumber_obj,
          0                     dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          xcf.keep_options      keep_options,
          xcf.keep_until        keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM xcf, dbinc
    WHERE db_key = this_db_key          -- belongs to this database
      AND dbinc.dbinc_key = xcf.dbinc_key
      AND (findControlfileProxyCopy.currentIncarnation = FALSE# OR
           this_dbinc_key = xcf.dbinc_key)
      AND (findControlfileProxyCopy.tag is NULL OR
           findControlfileProxyCopy.tag = tag)
      AND (findControlfileProxyCopy.pattern is NULL OR
           handle LIKE findControlfileProxyCopy.pattern)
      AND (findControlfileProxyCopy.completedAfter is NULL OR
           completion_time >= findControlfileProxyCopy.completedAfter)
      AND (findControlfileProxyCopy.completedBefore is NULL OR
           completion_time <= findControlfileProxyCopy.completedBefore)
      AND (findControlfileProxyCopy.untilSCN is NULL OR
           xcf.ckp_scn <= findControlfileProxyCopy.untilSCN)
      AND isStatusMatch(status,statusMask) = TRUE#
      AND (needstby is NULL OR
           nvl(controlfile_type,'B') = decode(needstby, TRUE#, 'S', 'B'))
    ORDER BY toSCN_act desc,            -- to find best backup
             stamp_con desc;            -- for LIST and to get most recent
CURSOR findControlfileBackup_c(
   currentIncarnation   IN     number         DEFAULT TRUE#
  ,pattern              IN     varchar2       DEFAULT NULL
  ,completedAfter       IN     date           DEFAULT NULL
  ,completedBefore      IN     date           DEFAULT NULL
  ,untilSCN             IN     number         DEFAULT NULL
  ,needstby             IN     number         DEFAULT NULL
  ,typemask             IN     binary_integer DEFAULT BScfile_all )
RETURN rcvRec_t IS
      -- Relaces: bcfq, lbcf.  Note that for lbcf, filtering for tags
      -- is now done elsewhere.
   SELECT backupSet_con_t       type_con,
          bcf_key               key_con,
          bcf_recid             recid_con,
          bcf_stamp             stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          bs.incr_level         bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          bcf.blocks            blocks_con,
          bcf.block_size        blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          bcf.create_time       cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          bcf.ckp_scn           toSCN_act,
          bcf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          bcf.dbinc_key         dbincKey_act,
          to_number(null)       level_act,
          0                     dfNumber_obj,
          0                     dfCreationSCN_obj,
          bcf.autobackup_sequence
                                cfSequence_obj,
          bcf.autobackup_date   cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          bs.keep_options       keep_options,
          bs.keep_until         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM bcf, bs, dbinc
    WHERE dbinc.db_key = this_db_key            -- belongs to this database
      AND bs.db_key = this_db_key               -- belongs to this database
      AND bcf.dbinc_key = dbinc.dbinc_key       -- join bcf and dbinc
      AND bcf.bs_key = bs.bs_key                -- join bcf and bs
      AND (findControlfileBackup_c.currentIncarnation = FALSE# OR
           this_dbinc_key = bcf.dbinc_key)
      AND (findControlfileBackup_c.completedAfter is NULL OR
           bs.completion_time >= findControlfileBackup_c.completedAfter)
      AND (findControlfileBackup_c.completedBefore is NULL OR
           bs.completion_time <= findControlfileBackup_c.completedBefore)
      AND (findControlfileBackup_c.untilSCN is NULL OR
           bcf.ckp_scn <= findControlfileBackup_c.untilSCN)
      AND (needstby is NULL OR
           nvl(controlfile_type,'B') = decode(needstby, TRUE#, 'S', 'B'))
      AND ((typemask = 0 AND bcf.autobackup_date IS NULL)  OR -- no autobackups
           (bitand(typemask, BScfile_all) != 0)            OR -- all backups
           (bcf.autobackup_date IS NOT NULL AND             -- only autobackups
            bitand(typemask, BScfile_auto) != 0))
    ORDER BY toSCN_act desc,
             stamp_con desc;
--------------------
-- SPFILE Backups --
--------------------
CURSOR findSpfileBackup_c(
   completedAfter        IN     date           DEFAULT NULL
  ,completedBefore       IN     date           DEFAULT NULL
  ,untilTime             IN     date           DEFAULT NULL)
RETURN rcvRec_t IS
   SELECT backupSet_con_t       type_con,
          bsf_recid             key_con,
          bsf_recid             recid_con,
          bsf_stamp             stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          bs.incr_level         bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          0                     blocks_con,
          0                     blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          0                     toSCN_act,
          modification_time     toTime_act,
          to_number(null)       rlgSCN_act,
          to_date(null)         rlgTime_act,
          to_number(null)       dbincKey_act,
          to_number(null)       level_act,
          to_number(null)       dfNumber_obj,
          to_number(null)       dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          bs.keep_options       keep_options,
          bs.keep_until         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM bsf, bs, db
    WHERE bsf.bs_key = bs.bs_key                -- join bsf and bs
      AND bs.db_key = this_db_key               -- belongs to this database
      AND bsf.db_key = db.db_key                -- join bsf and db
      AND (findSpfileBackup_c.completedAfter is NULL OR
           bs.completion_time >= findSpfileBackup_c.completedAfter)
      AND (findSpfileBackup_c.completedBefore is NULL OR
           bs.completion_time <= findSpfileBackup_c.completedBefore)
      AND (findSpfileBackup_c.untilTime is NULL OR
           modification_time <= findSpfileBackup_c.untilTime)
    ORDER BY toTime_act desc,                   -- for finding best backup
             stamp_con  desc;                   -- to get most recent
---------------------
-- Datafile Backup --
---------------------
getDatafileBackupLast   rcvRec_t;
CURSOR findDatafileBackup_c(
   sourcemask           IN     number
  ,fno                  IN     number         DEFAULT NULL
  ,crescn               IN     number         DEFAULT NULL
                                              -- makes sense when fno != NULL
  ,tag                  IN     varchar2       DEFAULT NULL
  ,pattern              IN     varchar2       DEFAULT NULL
  ,reset_scn            IN     number         DEFAULT NULL
  ,reset_time           IN     date           DEFAULT NULL
  ,level                IN     number         DEFAULT NULL
  ,completedAfter       IN     date           DEFAULT NULL
  ,completedBefore      IN     date           DEFAULT NULL
  ,untilSCN             IN     number         DEFAULT NULL
  ,statusMask           IN     binary_integer DEFAULT BSavailable                                          -- ignored for backupset because we didn't join bp
)
RETURN rcvRec_t IS
   SELECT imageCopy_con_t       type_con,
          cdf.cdf_key           key_con,
          cdf.cdf_recid         recid_con,
          cdf.cdf_stamp         stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_char(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          cdf.fname             fileName_con,
          cdf.tag               tag_con,
          to_number(null)       copyNumber_con,
          cdf.status            status_con,
          cdf.blocks            blocks_con,
          cdf.block_size        blockSize_con,
          'DISK'                deviceType_con,
          cdf.completion_time   compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          cdf.ckp_scn           toSCN_act,
          cdf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          cdf.dbinc_key         dbincKey_act,
          cdf.incr_level        level_act,
          cdf.file#             dfNumber_obj,
          cdf.create_scn        dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          cdf.keep_options      keep_options,
          cdf.keep_until        keep_until,
          cdf.abs_fuzzy_scn     afzSCN_act,
          cdf.rcv_fuzzy_time    rfzTime_act,
          cdf.rcv_fuzzy_scn     rfzSCN_act
     FROM cdf, dbinc
   WHERE (sourcemask is NULL OR bitand(sourcemask, imageCopy_con_t) != 0)
     AND (dbinc.db_key = this_db_key)            -- belongs to this database
     AND (dbinc.dbinc_key = cdf.dbinc_key)       -- join cdf and dbinc
     AND (findDatafileBackup_c.reset_scn is NULL OR
          (findDatafileBackup_c.reset_scn = dbinc.reset_scn AND
           findDatafileBackup_c.reset_time = dbinc.reset_time))
     AND ((findDatafileBackup_c.fno IS NULL AND file# != 0) OR  -- no ctrl bkps
          cdf.file# = findDatafileBackup_c.fno)
     AND (findDatafileBackup_c.crescn is NULL OR
          cdf.create_scn = findDatafileBackup_c.crescn)
     AND isStatusMatch(status,statusMask) = TRUE#
     AND (findDatafileBackup_c.tag is NULL OR
          tag = findDatafileBackup_c.tag)
     AND (findDatafileBackup_c.pattern is NULL OR
          cdf.fname LIKE findDatafileBackup_c.pattern)
     AND (findDatafileBackup_c.completedAfter is NULL OR
          cdf.completion_time >= findDatafileBackup_c.completedAfter)
     AND (findDatafileBackup_c.completedBefore is NULL OR
          cdf.completion_time <= findDatafileBackup_c.completedBefore)
     AND (findDatafileBackup_c.untilSCN is NULL OR
          cdf.ckp_scn <= findDatafileBackup_c.untilSCN)
     AND (findDatafileBackup_c.level is NULL OR
          cdf.incr_level <= findDatafileBackup_c.level)
   UNION ALL
   SELECT proxyCopy_con_t       type_con,
          xdf.xdf_key           key_con,
          xdf.xdf_recid         recid_con,
          xdf.xdf_stamp         stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_char(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          xdf.handle            fileName_con,
          xdf.tag               tag_con,
          to_number(null)       copyNumber_con,
          xdf.status            status_con,
          xdf.blocks            blocks_con,
          xdf.block_size        blockSize_con,
          xdf.device_type       deviceType_con,
          xdf.completion_time   compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          xdf.ckp_scn           toSCN_act,
          xdf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          xdf.dbinc_key         dbincKey_act,
          xdf.incr_level        level_act,
          xdf.file#             dfNumber_obj,
          xdf.create_scn        dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          xdf.keep_options      keep_options,
          xdf.keep_until        keep_until,
          xdf.abs_fuzzy_scn     afzSCN_act,
          xdf.rcv_fuzzy_time    rfzTime_act,
          xdf.rcv_fuzzy_scn     rfzSCN_act
     FROM xdf, dbinc
   WHERE (sourcemask is NULL OR bitand(sourcemask, proxyCopy_con_t) != 0)
     AND (dbinc.db_key = this_db_key)            -- belongs to this database
     AND (dbinc.dbinc_key = xdf.dbinc_key)       -- join xdf and dbinc
     AND (findDatafileBackup_c.reset_scn is NULL OR
          (findDatafileBackup_c.reset_scn = dbinc.reset_scn AND
           findDatafileBackup_c.reset_time = dbinc.reset_time))
     AND ((findDatafileBackup_c.fno IS NULL AND file# != 0) OR  -- no ctrl bkps
          xdf.file# = findDatafileBackup_c.fno)
     AND (findDatafileBackup_c.crescn is NULL OR
          xdf.create_scn = findDatafileBackup_c.crescn)
     AND isStatusMatch(xdf.status,statusMask) = TRUE#
     AND (findDatafileBackup_c.tag is NULL OR
          xdf.tag = findDatafileBackup_c.tag)
     AND (findDatafileBackup_c.pattern is NULL OR
          xdf.handle LIKE findDatafileBackup_c.pattern)
     AND (findDatafileBackup_c.completedAfter is NULL OR
          xdf.completion_time >= findDatafileBackup_c.completedAfter)
     AND (findDatafileBackup_c.completedBefore is NULL OR
          xdf.completion_time <= findDatafileBackup_c.completedBefore)
     AND (findDatafileBackup_c.untilSCN is NULL OR
          xdf.ckp_scn <= findDatafileBackup_c.untilSCN)
     AND (findDatafileBackup_c.level is NULL OR
          xdf.incr_level <= findDatafileBackup_c.level)
   UNION ALL
   SELECT backupSet_con_t       type_con,
          bdf.bdf_key           key_con,
          bdf.bdf_recid             recid_con,
          bdf.bdf_stamp             stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid              bsRecid_con,
          bs.bs_stamp              bsStamp_con,
          bs.bs_key             bsKey_con,
          bs.incr_level  bsLevel_con,
          bs.bck_type        bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          bdf.blocks            blocks_con,
          bdf.block_size        blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          decode(bdf.incr_scn, 0, full_act_t, incremental_act_t)
                                type_act,
          bdf.incr_scn          fromSCN_act,
          bdf.ckp_scn           toSCN_act,
          bdf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          bdf.dbinc_key         dbincKey_act,
          bdf.incr_level        level_act,
          bdf.file#             dfNumber_obj,
          bdf.create_scn        dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          bs.keep_options       keep_options,
          bs.keep_until         keep_until,
          bdf.abs_fuzzy_scn     afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM  bdf, bs, dbinc
   WHERE (sourcemask is NULL OR bitand(sourcemask, backupSet_con_t) != 0)
     AND (dbinc.db_key = this_db_key)            -- belongs to this database
     AND (bs.db_key = this_db_key)               -- belongs to this database
     AND (bdf.dbinc_key = dbinc.dbinc_key)       -- join bdf and dbinc
     AND (bdf.bs_key = bs.bs_key)                -- join bdf and bs
     AND (findDatafileBackup_c.reset_scn is NULL  OR
          (findDatafileBackup_c.reset_scn  = dbinc.reset_scn AND
           findDatafileBackup_c.reset_time = dbinc.reset_time))
     AND ((findDatafileBackup_c.fno IS NULL AND file# != 0) OR  -- no ctrl bkps
           file# = findDatafileBackup_c.fno)
     AND (findDatafileBackup_c.crescn is NULL OR
          bdf.create_scn = findDatafileBackup_c.crescn)
     AND (findDatafileBackup_c.completedAfter is NULL OR
          bs.completion_time >= findDatafileBackup_c.completedAfter)
     AND (findDatafileBackup_c.completedBefore is NULL OR
          bs.completion_time <= findDatafileBackup_c.completedBefore)
     AND (findDatafileBackup_c.untilSCN is NULL OR
          bdf.ckp_scn <= findDatafileBackup_c.untilSCN)
     AND (findDatafileBackup_c.level is NULL OR
          bdf.incr_level <= findDatafileBackup_c.level)
  ORDER BY  33,            -- dfNumber_obj
            27 desc,       -- toSCN_act
             4 desc;       -- stamp_con
CURSOR findDatafileCopyKey(
   copyKey              IN     number
  ,statusMask           IN     binary_integer)
RETURN rcvRec_t IS
   -- Replaces these cursors:  cursor in translateDataFileCopyKey
   SELECT imageCopy_con_t       type_con,
          cdf_key               key_con,
          cdf_recid             recid_con,
          cdf_stamp             stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_char(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          fname                 fileName_con,
          tag                   tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          blocks                blocks_con,
          block_size            blockSize_con,
          'DISK'                deviceType_con,
          completion_time       compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          cdf.ckp_scn           toSCN_act,
          cdf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          cdf.dbinc_key         dbincKey_act,
          incr_level            level_act,
          file#                 dfNumber_obj,
          create_scn            dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          cdf.keep_options      keep_options,
          cdf.keep_until        keep_until,
          cdf.abs_fuzzy_scn     afzSCN_act,
          cdf.rcv_fuzzy_time    rfzTime_act,
          cdf.rcv_fuzzy_scn     rfzSCN_act
     FROM cdf, dbinc
    WHERE dbinc.db_key = this_db_key            -- belongs to this database
      AND dbinc.dbinc_key = cdf.dbinc_key       -- join cdf and dbinc
      AND (findDatafileCopyKey.copyKey = cdf_key)
      AND isStatusMatch(status,statusMask) = TRUE#
    ORDER BY dfNumber_obj,              -- for duplicate filtering
             toSCN_act desc,            -- for tag translation
             stamp_con desc;            -- to get most recent
CURSOR findBackupsetFiles(
   bskey                IN     number)
RETURN rcvRec_t IS
   -- datafiles
   SELECT backupSet_con_t       type_con,
          bdf_key               key_con,
          bdf_recid             recid_con,
          bdf_stamp             stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          bs.incr_level         bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          bdf.blocks            blocks_con,
          bdf.block_size        blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          decode(bdf.incr_scn, 0, full_act_t, incremental_act_t)
                                type_act,
          bdf.incr_scn          fromSCN_act,
          bdf.ckp_scn           toSCN_act,
          bdf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          bdf.dbinc_key         dbincKey_act,
          bdf.incr_level        level_act,
          file#                 dfNumber_obj,
          create_scn            dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          bs.keep_options       keep_options,
          bs.keep_until         keep_until,
          bdf.abs_fuzzy_scn     afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM bdf, bs, dbinc
    WHERE (allIncarnations = TRUE# OR dbinc.dbinc_key = this_dbinc_key)
      AND dbinc.db_key     = this_db_key        -- belongs to this database
      AND dbinc.dbinc_key  = bdf.dbinc_key      -- join bdf and dbinc
      AND bdf.bs_key       = bs.bs_key          -- join bdf and bs
      AND bs.bs_key        = bskey
    UNION ALL
   -- controlfile
   SELECT backupSet_con_t       type_con,
          bcf_key               key_con,
          bcf_recid             recid_con,
          bcf_stamp             stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          bs.incr_level         bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          nvl(bcf.blocks,0)     blocks_con,
          bcf.block_size        blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          to_number(null)       fromSCN_act,
          bcf.ckp_scn           toSCN_act,
          bcf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          bcf.dbinc_key         dbincKey_act,
          to_number(null)       level_act,
          0                     dfNumber_obj,
          0                     dfCreationSCN_obj,
          bcf.autobackup_sequence
                                cfSequence_obj,
          bcf.autobackup_date   cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          bs.keep_options       keep_options,
          bs.keep_until         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM bcf, bs, dbinc
    WHERE (allIncarnations = TRUE# OR dbinc.dbinc_key = this_dbinc_key)
      AND dbinc.db_key     = this_db_key        -- belongs to this database
      AND dbinc.dbinc_key  = bcf.dbinc_key      -- join bcf and dbinc
      AND bcf.bs_key       = bs.bs_key          -- join bcf and bs
      AND bs.bs_key        = bskey
    UNION ALL
   -- SPFILE
   SELECT backupSet_con_t       type_con,
          bsf_recid             key_con,
          bsf_recid             recid_con,
          bsf_stamp             stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          bs.incr_level         bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          0                     blocks_con,
          0                     blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          0                     toSCN_act,
          modification_time     toTime_act,
          to_number(null)       rlgSCN_act,
          to_date(null)         rlgTime_act,
          to_number(null)       dbincKey_act,
          to_number(null)       level_act,
          to_number(null)       dfNumber_obj,
          to_number(null)       dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          bs.keep_options       keep_options,
          bs.keep_until         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM bsf, bs, db
    WHERE bsf.bs_key = bs.bs_key                -- join bsf and bs
      AND bs.db_key = this_db_key               -- belongs to this database
      AND bsf.db_key = db.db_key                -- join bsf and db
      AND bs.bs_key = bskey
    UNION ALL
    -- archived logs
   SELECT backupSet_con_t       type_con,
          brl.brl_key           key_con,
          brl.brl_recid         recid_con,
          brl.brl_stamp         stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          to_number(null)       bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          brl.blocks            blocks_con,
          brl.block_size        blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          to_number(null)       fromSCN_act,
          to_number(null)       toSCN_act,
          to_date(null)         toTime_act,
          to_number(null)       rlgSCN_act,
          to_date(null)         rlgTime_act,
          dbinc.dbinc_key       dbincKey_act,
          to_number(null)       level_act,
          to_number(null)       dfNumber_obj,
          to_number(null)       dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          brl.sequence#         logSequence_obj,
          brl.thread#           logThread_obj,
          dbinc.reset_scn       logRlgSCN_obj,
          dbinc.reset_time      logRlgTime_obj,
          brl.low_scn           logLowSCN_obj,
          brl.low_time          logLowTime_obj,
          brl.next_scn          logNextSCN_obj,
          brl.next_time         logNextTime_obj,
          to_number(null)       keep_options,
          to_date(null)         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM brl, bs, dbinc
    WHERE (allIncarnations = TRUE# OR dbinc.dbinc_key = this_dbinc_key)
      AND dbinc.db_key     = this_db_key        -- belongs to this database
      AND dbinc.dbinc_key  = brl.dbinc_key      -- join brl and dbinc
      AND brl.bs_key       = bs.bs_key          -- join brl and bs
      AND bs.bs_key        = bskey
    ORDER BY 33, -- dfNumber_obj
             38, -- logThread_obj
             37; -- logSequence_obj
------------------
-- Proxy Copies --
------------------
CURSOR findProxyCopy(
   tag                  IN     varchar2       DEFAULT NULL
  ,handle               IN     varchar2       DEFAULT NULL
  ,deviceType           IN     varchar2       DEFAULT NULL
  ,statusMask           IN     binary_integer)
RETURN rcvRec_t IS
   SELECT proxyCopy_con_t       type_con,
          xdf_key               key_con,
          xdf_recid             recid_con,
          xdf_stamp             stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_char(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          handle                fileName_con,
          tag                   tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          blocks                blocks_con,
          block_size            blockSize_con,
          device_type           deviceType_con,
          completion_time       compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          xdf.ckp_scn           toSCN_act,
          xdf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          xdf.dbinc_key         dbincKey_act,
          incr_level            level_act,
          file#                 dfNumber_obj,
          create_scn            dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          xdf.keep_options      keep_options,
          xdf.keep_until        keep_until,
          xdf.abs_fuzzy_scn     afzSCN_act,
          xdf.rcv_fuzzy_time    rfzTime_act,
          xdf.rcv_fuzzy_scn     rfzSCN_act
     FROM xdf, dbinc
    WHERE dbinc.db_key = this_db_key            -- belongs to this database
      AND dbinc.dbinc_key = xdf.dbinc_key       -- join xdf and dbinc
      AND (findProxyCopy.tag IS NULL OR
           findProxyCopy.tag = tag)
      AND (findProxyCopy.handle IS NULL OR
           findProxyCopy.handle = handle)
      AND (findProxyCopy.deviceType IS NULL OR
           findProxyCopy.deviceType = device_type)
      AND isStatusMatch(status,statusMask) = TRUE#
    UNION ALL
   SELECT proxyCopy_con_t       type_con,
          xcf_key               key_con,
          xcf_recid             recid_con,
          xcf_stamp             stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_char(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          handle                fileName_con,
          tag                   tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          to_number(null)       blocks_con,     -- xcf doesn't have blocks
          block_size            blockSize_con,
          device_type           deviceType_con,
          completion_time       compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          xcf.ckp_scn           toSCN_act,
          xcf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          xcf.dbinc_key         dbincKey_act,
          to_number(null)       level_act,
          0                     dfNumber_obj,
          0                     dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          xcf.keep_options      keep_options,
          xcf.keep_until        keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM xcf, dbinc
    WHERE db_key = this_db_key          -- belongs to this database
      AND dbinc.dbinc_key = xcf.dbinc_key       -- join dbinc and xcf
      AND (findProxyCopy.tag IS NULL OR
           findProxyCopy.tag = tag)
      AND (findProxyCopy.handle IS NULL OR
           findProxyCopy.handle = handle)
      AND (findProxyCopy.deviceType IS NULL OR
           findProxyCopy.deviceType = device_type)
      AND isStatusMatch(status,statusMask) = TRUE#;
CURSOR findProxyCopyKey(
   key                  IN     number         DEFAULT NULL
  ,deviceType           IN     varchar2       DEFAULT NULL
  ,statusMask           IN     binary_integer)
RETURN rcvRec_t IS
   SELECT proxyCopy_con_t       type_con,
          xdf_key               key_con,
          xdf_recid             recid_con,
          xdf_stamp             stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_date(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          handle                fileName_con,
          tag                   tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          blocks                blocks_con,
          block_size            blockSize_con,
          device_type           deviceType_con,
          completion_time       compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          xdf.ckp_scn           toSCN_act,
          xdf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          xdf.dbinc_key         dbincKey_act,
          incr_level            level_act,
          file#                 dfNumber_obj,
          create_scn            dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          xdf.keep_options      keep_options,
          xdf.keep_until        keep_until,
          xdf.abs_fuzzy_scn     afzSCN_act,
          xdf.rcv_fuzzy_time    rfzTime_act,
          xdf.rcv_fuzzy_scn     rfzSCN_act
     FROM xdf, dbinc
    WHERE dbinc.db_key = this_db_key            -- belongs to this database
      AND dbinc.dbinc_key = xdf.dbinc_key       -- join xdf and dbinc
      AND (findProxyCopyKey.key = xdf_key)
      AND (findProxyCopyKey.deviceType IS NULL OR
           findProxyCopyKey.deviceType = device_type)
      AND isStatusMatch(status,statusMask) = TRUE#
    UNION ALL
   SELECT proxyCopy_con_t       type_con,
          xcf_key               key_con,
          xcf_recid             recid_con,
          xcf_stamp             stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_date(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          handle                fileName_con,
          tag                   tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          to_number(null)       blocks_con,     -- xcf doesn't have blocks
          block_size            blockSize_con,
          device_type           deviceType_con,
          completion_time       compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          xcf.ckp_scn           toSCN_act,
          xcf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          xcf.dbinc_key         dbincKey_act,
          to_number(null)       level_act,
          0                     dfNumber_obj,
          0                     dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          xcf.keep_options      keep_options,
          xcf.keep_until        keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM xcf, dbinc
    WHERE db_key = this_db_key          -- belongs to this database
      AND dbinc.dbinc_key = xcf.dbinc_key       -- join dbinc and xcf
      AND (findProxyCopyKey.key = xcf_key)
      AND (findProxyCopyKey.deviceType IS NULL OR
           findProxyCopyKey.deviceType = device_type)
      AND isStatusMatch(status,statusMask) = TRUE#;
------------------------
-- Archivelog Backups --
------------------------
CURSOR findArchivedLogCopy(
   currentIncarnation   IN     number
  ,thread               IN     number
  ,sequence             IN     number
  ,lowSCN               IN     number
  ,pattern              IN     varchar2       DEFAULT NULL
  ,completedAfter       IN     date           DEFAULT NULL
  ,completedBefore      IN     date           DEFAULT NULL
  ,statusMask           IN     binary_integer
  ,needstby             IN     number         DEFAULT NULL)
RETURN rcvRec_t IS
   -- Replaces these cursors:  lcal
   SELECT imageCopy_con_t       type_con,
          al_key                key_con,
          recid                 recid_con,
          stamp                 stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_date(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          name                  fileName_con,
          to_date(null)         tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          blocks                blocks_con,
          block_size            blockSize_con,
          'DISK'                deviceType_con,
          completion_time       compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          to_number(null)       fromSCN_act,
          to_number(null)       toSCN_act,
          to_date(null)         toTime_act,
          to_number(null)       rlgSCN_act,
          to_date(null)         rlgTime_act,
          dbinc_key             dbincKey_act,
          to_number(null)       level_act,
          to_number(null)       dfNumber_obj,
          to_number(null)       dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          sequence#             logSequence_obj,
          thread#               logThread_obj,
          resetlogs_change#     logRlgSCN_obj,
          resetlogs_time        logRlgTime_obj,
          first_change#         logLowSCN_obj,
          first_time            logLowTime_obj,
          next_change#          logNextSCN_obj,
          next_time             logNextTime_obj,
          to_number(null)       keep_options,
          to_date(null)         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM rc_archived_log
    WHERE db_key = this_db_key                    -- belongs to this database
      AND(findArchivedLogCopy.currentIncarnation = FALSE# OR
           this_dbinc_key = dbinc_key)
      AND (thread IS NULL OR thread# = thread)
      AND (sequence IS NULL OR sequence# = sequence)
      AND (lowSCN IS NULL OR first_change# = lowSCN)
      -- Pattern isn't really needed here.  The LIKE clause should be
      -- handled during name translation by krmkaltr.  However, krmg.y
      -- allows the LIKE clause as a listQualifier, so we need to support
      -- it for that bizzarre case.
      AND (pattern IS NULL OR name LIKE pattern)
      AND (completedAfter IS NULL OR completion_time >= completedAfter)
      AND (completedBefore IS NULL OR completion_time <= completedBefore)
      AND isStatusMatch(status,statusMask) = TRUE#
      AND (needstby is NULL OR
           nvl(is_standby, 'NO') = decode(needstby, TRUE#, 'YES', 'NO'))
      -- bug-1479780: translate should return only archived logs and not
      --              online logs
      AND (archived = 'YES')
      AND (tc_thread IS NULL OR thread# = tc_thread)
      AND (tc_fromSeq IS NULL OR sequence# >= tc_fromSeq)
      AND (tc_toSeq IS NULL OR sequence# <= tc_toSeq)
      AND (tc_fromSCN IS NULL OR next_change# > tc_fromSCN)
      AND (tc_toSCN IS NULL OR first_change# < tc_toSCN)
      AND (tc_pattern IS NULL or name like tc_pattern)
      AND (tc_fromTime IS NULL or next_time > tc_fromTime)
      AND (tc_toTime IS NULL or first_time <= tc_toTime)
    ORDER BY thread#, sequence#, stamp_con desc;
CURSOR findArcLogBackup(
   currentIncarnation   IN     number
  ,thread               IN     number
  ,sequence             IN     number
  ,lowSCN               IN     number
  ,completedAfter       IN     date           DEFAULT NULL
  ,completedBefore      IN     date           DEFAULT NULL)
RETURN rcvRec_t IS
   SELECT backupSet_con_t       type_con,
          brl.brl_key           key_con,
          brl.brl_recid         recid_con,
          brl.brl_stamp         stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          to_number(null)       bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          brl.blocks            blocks_con,
          brl.block_size        blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          to_number(null)       fromSCN_act,
          to_number(null)       toSCN_act,
          to_date(null)         toTime_act,
          to_number(null)       rlgSCN_act,
          to_date(null)         rlgTime_act,
          dbinc.dbinc_key       dbincKey_act,
          to_number(null)       level_act,
          to_number(null)       dfNumber_obj,
          to_number(null)       dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          brl.sequence#         logSequence_obj,
          brl.thread#           logThread_obj,
          dbinc.reset_scn       logRlgSCN_obj,
          dbinc.reset_time      logRlgTime_obj,
          brl.low_scn           logLowSCN_obj,
          brl.low_time          logLowTime_obj,
          brl.next_scn          logNextSCN_obj,
          brl.next_time         logNextTime_obj,
          to_number(null)       keep_options,
          to_date(null)         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM brl, bs, dbinc
    WHERE dbinc.db_key = this_db_key             -- belongs to this database
      AND (currentIncarnation = FALSE# OR
           this_dbinc_key = dbinc.dbinc_key)
      AND (thread IS NULL OR brl.thread# = thread)
      AND (sequence IS NULL OR brl.sequence# = sequence)
      AND (lowSCN IS NULL OR brl.low_scn = lowSCN)
      AND dbinc.dbinc_key = brl.dbinc_key      -- join dbinc, brl
      AND bs.bs_key       = brl.bs_key         -- join bs, brl
      -- LIKE as a listOperand is not allowed for LIST BACKUP, so
      -- pattern is ignored here.
      AND (completedAfter  IS NULL OR bs.completion_time >= completedAfter)
      AND (completedBefore IS NULL OR bs.completion_time <= completedBefore)
      AND (tc_thread IS NULL OR brl.thread# = tc_thread)
      AND (tc_fromSeq IS NULL OR brl.sequence# >= tc_fromSeq)
      AND (tc_toSeq IS NULL OR brl.sequence# <= tc_toSeq)
      AND (tc_fromSCN IS NULL OR brl.next_scn > tc_fromSCN)
      AND (tc_toSCN IS NULL OR brl.low_scn < tc_toSCN)
      AND (tc_fromTime IS NULL or brl.next_time > tc_fromTime)
      AND (tc_toTime IS NULL or brl.low_time <= tc_toTime)
    ORDER BY brl.thread#, brl.sequence#, stamp_con desc;
CURSOR findAllBackupPiece(
   backupType           IN     binary_integer
  ,tag                  IN     varchar2
  ,statusMask           IN     binary_integer
  ,completedAfter       IN     date
  ,completedBefore      IN     date)
RETURN rcvRec_t IS
   SELECT backupset_con_t       type_con,
          bp.bp_key             key_con,
          bp.bp_recid           recid_con,
          bp.bp_stamp           stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          bs.incr_level         bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          bp.handle             fileName_con,
          bp.tag                tag_con,
          bp.copy#              copyNumber_con,
          bp.status             status_con,
          to_number(null)       blocks_con,
          to_number(null)       blockSize_con,
          bp.device_type        deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          bp.piece#             pieceNumber_con,
          bp.completion_time    bpCompTime_con,
          to_number(null)       type_act,
          to_number(null)       fromSCN_act,
          to_number(null)       toSCN_act,
          to_date(null)         toTime_act,
          to_number(null)       rlgSCN_act,
          to_date(null)         rlgTime_act,
          to_number(null)       dbincKey_act,
          to_number(null)       level_act,
          to_number(null)       dfNumber_obj,
          to_number(null)       dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          bs.keep_options       keep_options,
          bs.keep_until         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM bp, bs
    WHERE (bp.bs_key = bs.bs_key)       -- join bp and bs
      AND (bs.db_key = this_db_key)     -- this database
      AND (completedAfter IS NULL OR bs.completion_time >= completedAfter)
      AND (completedBefore IS NULL OR bs.completion_time <= completedBefore)
      AND (findAllBackupPiece.tag IS NULL or bp.tag = findAllBackupPiece.tag)
      AND (isDeviceTypeAllocated(bp.device_type) = TRUE#)
      AND (isStatusMatch(bp.status, statusMask) = TRUE#)
      AND (findAllBackupPiece.backupType IS NULL OR
           isBackupTypeMatch(bs.bck_type, backupType) = TRUE#)
    -- the order here is important
    ORDER BY bs.bs_key, bp.device_type, bp.tag, bp.copy#, bp.piece#;
---------------------------
-- Backup Set Validation --
---------------------------
getValidBackupSetLast   validBackupSetRec_t;
getValidBackupSetCursor varchar2(30);    -- to indicate what cursor was used
-- This cursor returns the device_type(s), tags, and copy#'s for which all
-- backup pieces of the specified backup set are available.  A code field
-- is also provided which indicates whether the ORDER BY included all
-- 3 fields (1), or just device_type and tag (2), or just device_type (3).
-- NOTE:  If you change the ORDER BY in the cursor, you probably need
--        to change getValidBackupSet.  It depends on the order-by.
CURSOR findValidBackupSet_c(
   bsKey                   IN number
  ,pieceCount              IN number
  ,deviceType              IN varchar2 DEFAULT NULL
  ,tag                     IN varchar2 DEFAULT NULL
  ,mask                    IN binary_integer)
RETURN dbms_rcvman.validBackupSetRec_t IS
   -- N.B.
   -- partial_avail means the backup set is unusable either because some
   -- pieces are unavailable, expired or total backuppieces < existing
   -- pieces. In other words the backupset is INCOMPLETE.
   -- A partial_avail backupset can be made available by doing crosscheck,
   -- catalog backuppiece(TBD), making pieces available.
   -- Group by device_type, tag, and copy#.  This way, we can see if there is
   -- a set of pieces with the same copy# and tag.
   SELECT device_type, tag, copy#, 1
     FROM rc_backup_piece
    WHERE bs_key = findValidBackupSet_c.bsKey
      AND isStatusMatch(status,mask) = TRUE#
      AND (findValidBackupSet_c.tag IS NULL OR
           findValidBackupSet_c.tag = tag)
      AND (findValidBackupSet_c.deviceType IS NULL OR
           findValidBackupSet_c.deviceType = device_type)
    GROUP BY device_type, tag, copy#
   HAVING ((bitand(mask, dbms_rcvman.BSpartial_avail) = 0 AND
            count(DISTINCT piece#) = findValidBackupSet_c.pieceCount) OR
           (bitand(mask, dbms_rcvman.BSpartial_avail) <> 0 AND
            count(DISTINCT piece#) <= findValidBackupSet_c.pieceCount))
    UNION ALL
   -- Allow a mix of copy numbers, but still the same tag.  It is possible
   -- that the backup set is available only if pieces with different copy#'s
   -- are combined to form the complete set.
   SELECT device_type, tag, to_number(null), 2
     FROM rc_backup_piece
    WHERE bs_key = findValidBackupSet_c.bsKey
      AND ((bitand(mask, dbms_rcvman.BSavailable) <> 0   AND status = 'A') OR
           (bitand(mask, dbms_rcvman.BSunavailable) <> 0 AND status = 'U') OR
           (bitand(mask, dbms_rcvman.BSdeleted) <> 0     AND status = 'D') OR
           (bitand(mask, dbms_rcvman.BSexpired) <> 0     AND status = 'X') OR
           (bitand(mask, dbms_rcvman.BSpartial_avail) <> 0 AND
            (status = 'A' OR status = 'U')))
      AND (findValidBackupSet_c.tag IS NULL OR
           findValidBackupSet_c.tag = tag)
      AND (findValidBackupSet_c.deviceType IS NULL OR
           findValidBackupSet_c.deviceType = device_type)
    GROUP BY device_type, tag
   HAVING ((bitand(mask, dbms_rcvman.BSpartial_avail) = 0 AND
            count(DISTINCT piece#) = findValidBackupSet_c.pieceCount) OR
           (bitand(mask, dbms_rcvman.BSpartial_avail) <> 0 AND
            count(DISTINCT piece#) <= findValidBackupSet_c.pieceCount))
    UNION ALL
   -- Allow a mix of tags.  It is possible that the backup set is available
   -- only if we combine pieces with different tags.  Since we are mixing
   -- tags, we are definitly also going to be mixing copy#s because any set of
   -- pieces composed of pieces with different tags must also have different
   -- copy#s.  Note that this is really moot until BACKUP BACKUP PIECE is
   -- implemented.  Until then all pieces of a backup set will have the same
   -- tag, or no tag at all.
   SELECT device_type, to_char(null), to_number(null), 3
     FROM rc_backup_piece
    WHERE bs_key = findValidBackupSet_c.bsKey
      AND ((bitand(mask, dbms_rcvman.BSavailable) <> 0   AND status = 'A') OR
           (bitand(mask, dbms_rcvman.BSunavailable) <> 0 AND status = 'U') OR
           (bitand(mask, dbms_rcvman.BSdeleted) <> 0     AND status = 'D') OR
           (bitand(mask, dbms_rcvman.BSexpired) <> 0     AND status = 'X') OR
           (bitand(mask, dbms_rcvman.BSpartial_avail) <> 0 AND
            (status = 'A' OR status = 'U')))
      AND (findValidBackupSet_c.tag IS NULL OR
           findValidBackupSet_c.tag = tag)
      AND (findValidBackupSet_c.deviceType IS NULL OR
           findValidBackupSet_c.deviceType = device_type)
    GROUP BY device_type
   HAVING ((bitand(mask, dbms_rcvman.BSpartial_avail) = 0 AND
            count(DISTINCT piece#) = findValidBackupSet_c.pieceCount) OR
           (bitand(mask, dbms_rcvman.BSpartial_avail) <> 0 AND
            count(DISTINCT piece#) <= findValidBackupSet_c.pieceCount))
    ORDER BY 1,2,3,4;
---------------------------------------------------------
-- findValidBackupSet_c optimized for 1 piece backupset --
----------------------------------------------------------
CURSOR findValidBackupSet1P_c(
   bsKey                   IN number
  ,pieceCount              IN number
  ,deviceType              IN varchar2 DEFAULT NULL
  ,tag                     IN varchar2 DEFAULT NULL
  ,mask                    IN binary_integer)
RETURN validBackupSetRec_t IS
   -- N.B.
   -- We don't need to check partial_avail mask because there is just
   -- one piece in this backupset. It just completely satisfies
   -- statusMask provided.
   -- We also don't need to group by
   -- o device type because the 1 piece should completely exists on one device
   -- o tag because the 1 piece should have the tag specified
   -- o copy# because each piece has distinct copy number
   --
   SELECT device_type, tag, copy#, 1
      FROM rc_backup_piece
   WHERE bs_key = findValidBackupSet1P_c.bsKey
      AND isStatusMatch(status,mask) = TRUE#
      AND (findValidBackupSet1P_c.tag IS NULL OR
           findValidBackupSet1P_c.tag = tag)
      AND (findValidBackupSet1P_c.deviceType IS NULL OR
           findValidBackupSet1P_c.deviceType = device_type) ;
-------------------
-- Backup Pieces --
-------------------
-- Replaces the following 8.1.x cursors:
-- bsq1, bsq2
-- NOTE:  no indexs are used, so this cusor is likely to require a full
-- table scan of the bp table.
CURSOR findBackupPiece_c(
   tag          IN     varchar2 DEFAULT NULL
  ,handle       IN     varchar2 DEFAULT NULL
  ,deviceType   IN     varchar2 DEFAULT NULL
  ,copyNumber   IN     number   DEFAULT NULL
  ,statusMask   IN     binary_integer)
RETURN bpRec_t IS
   SELECT bp_recid,
          bp_stamp,
          bp_key,
          bp.bs_key,
          set_stamp,
          set_count,
          piece#,
          copy#,
          bp.status,
          bp.completion_time,
          handle,
          tag,
          device_type
     FROM bp, bs
    WHERE bp.db_key = this_db_key               -- belongs to this db
      AND bs.db_key = this_db_key               -- belongs to this db
      AND bp.bs_key = bs.bs_key                 -- join bp and bs
      AND (findBackupPiece_c.tag IS NULL OR
           tag = findBackupPiece_c.tag)
      AND (findBackupPiece_c.handle IS NULL OR
           handle = findBackupPiece_c.handle)
      AND (findBackupPiece_c.deviceType IS NULL OR
           device_type = findBackupPiece_c.deviceType)
      AND (findBackupPiece_c.copyNumber IS NULL OR
           copy# = findBackupPiece_c.copyNumber)
      AND isStatusMatch(bp.status,statusMask) = TRUE#
    ORDER BY piece#, copy# desc, bp_stamp desc;
CURSOR findBackupPieceBpKey(
   bpKey        IN     number
  ,tag          IN     varchar2 DEFAULT NULL
  ,handle       IN     varchar2 DEFAULT NULL
  ,deviceType   IN     varchar2 DEFAULT NULL
  ,copyNumber   IN     number   DEFAULT NULL
  ,statusMask   IN     binary_integer)
RETURN bpRec_t IS
   SELECT bp_recid,
          bp_stamp,
          bp_key,
          bp.bs_key,
          set_stamp,
          set_count,
          piece#,
          copy#,
          bp.status,
          bp.completion_time,
          handle,
          tag,
          device_type
     FROM bp, bs
    WHERE bp.db_key = this_db_key
      AND bs.db_key = this_db_key
      AND bp.bs_key = bs.bs_key
      AND (bp_key = findBackupPieceBpKey.bpkey)
      AND (findBackupPieceBpKey.tag IS NULL OR
           tag = findBackupPieceBpKey.tag)
      AND (findBackupPieceBpKey.handle IS NULL OR
           handle = findBackupPieceBpKey.handle)
      AND (findBackupPieceBpKey.deviceType IS NULL OR
           device_type = findBackupPieceBpKey.deviceType)
      AND (findBackupPieceBpKey.copyNumber IS NULL OR
           copy# = findBackupPieceBpKey.copyNumber)
      AND isStatusMatch(bp.status,statusMask) = TRUE#
    ORDER BY piece#, copy# desc, bp_stamp desc;
CURSOR findBackupPieceBsKey(
   bsKey        IN     number
  ,tag          IN     varchar2 DEFAULT NULL
  ,handle       IN     varchar2 DEFAULT NULL
  ,deviceType   IN     varchar2 DEFAULT NULL
  ,copyNumber   IN     number   DEFAULT NULL
  ,statusMask   IN     binary_integer)
RETURN bpRec_t IS
   SELECT bp_recid,
          bp_stamp,
          bp_key,
          bp.bs_key,
          set_stamp,
          set_count,
          piece#,
          copy#,
          bp.status,
          bp.completion_time,
          handle,
          tag,
          device_type
     FROM bp, bs
    WHERE bp.db_key = this_db_key
      AND bs.db_key = this_db_key
      AND bp.bs_key = bs.bs_key
      AND (bs.bs_key = findBackupPieceBsKey.bsKey)
      AND (findBackupPieceBsKey.tag IS NULL OR
           tag = findBackupPieceBsKey.tag)
      AND (findBackupPieceBsKey.handle IS NULL OR
           handle = findBackupPieceBsKey.handle)
      AND (findBackupPieceBsKey.deviceType IS NULL OR
           device_type = findBackupPieceBsKey.deviceType)
      AND (findBackupPieceBsKey.copyNumber IS NULL OR
           copy# = findBackupPieceBsKey.copyNumber)
      AND isStatusMatch(bp.status,statusMask) = TRUE#
    ORDER BY piece#, copy# desc, bp_stamp desc;
----------------------
-- Name Translation --
----------------------
TYPE noRows_t IS RECORD
(
   error        number,                 -- error number
   msg          varchar2(100)           -- error msg
);
-- The tablespace_list is used to hold the list of tablespace names to
-- skip when the SKIP TABLESPACE clause is specified.
TYPE tablespaceList_t is table of rc_tablespace.name%TYPE
  index by binary_integer;
skipTablespaceList      tablespaceList_t;
skipTablespaceCount     number;         -- number of tablespaces in list
--------------------------
-- Datafile Translation --
--------------------------
getDatafileCursor varchar2(30);         -- pointer to current cursor
getDatafileNoRows noRows_t;             -- Set by function that opens cursor
getDatafileLast   dfRec_t;              -- The last row returned
-- Translate the database within an SCN range. The datafiles are not part of
-- the database at their until the dictionary transaction commits.
-- Therefore the creation scn must be less than toSCN.
-- ### offline drop makes the above statement dangerous, so allow <=
-- Note that fromSCN and toSCN must not be null.
-- Note that inBackup field has value 1 if included_in_database_backup is 'YES'
CURSOR translateDatabase_c(
   fromSCN number,
   toSCN   number)
RETURN dfRec_t IS
   SELECT file#, creation_change#, creation_time,
          name, tablespace_name, ts#,
          null, blocks, block_size, bytes / 1024,
          null, stop_change#, read_only, rfile#,
          decode(included_in_database_backup, 'YES', 1, 0),
          aux_name
     FROM rc_datafile
    WHERE db_key = this_db_key AND              -- belongs to this database
          dbinc_key = this_dbinc_key AND
          creation_change# <= toSCN AND
          (drop_change# is null OR drop_change# > fromSCN)
    ORDER BY file#;
-- Translate a tablespace name (always relative to current time)
-- Note: inBackup field has value 1 if included_in_database_backup is 'YES'
CURSOR translateTablespace_c(
   tsName varchar2)
RETURN dfRec_t IS
   SELECT file#, creation_change#, creation_time,
          name, tablespace_name, ts#,
          null, blocks, block_size, bytes / 1024,
          null, stop_change#, read_only, rfile#,
          decode(included_in_database_backup, 'YES', 1, 0),
          aux_name
     FROM rc_datafile
    WHERE db_key = this_db_key AND              -- part of this db
          tablespace_name = translateTablespace_c.tsName AND
          dbinc_key = this_dbinc_key AND
          ((untilSCN is null AND drop_change# is null) OR
           ((creation_change# <= untilSCN) AND
            (drop_change# is null or drop_change# > untilSCN)))
    ORDER BY file#;
-- Translate a datafile name (always relative to current time
-- Note: inBackup field has value 1 if included_in_database_backup is 'YES'
CURSOR translateDatafileName(
   fileName varchar2)
RETURN dfRec_t IS
   SELECT file#, creation_change#, creation_time,
          name, tablespace_name, ts#,
          null, blocks, block_size, bytes / 1024,
          null, stop_change#, read_only, rfile#,
          decode(included_in_database_backup, 'YES', 1, 0),
          aux_name
     FROM rc_datafile
    WHERE db_key = this_db_key AND              -- belongs to this database
          name = translateDatafilename.fileName AND -- filename matches
          dbinc_key = this_dbinc_key AND
          drop_change# is null AND      -- filename currently part of db
          (untilSCN is null OR creation_change# < untilSCN) AND
           -- following "and" clause to detect ambiguous names
          ((untilSCN is null) OR         -- no until clause
           ((untilTime is not null) AND not exists
            (SELECT 1
               FROM rc_datafile
              WHERE dbinc_key = this_dbinc_key AND
                    name = translateDatafilename.fileName AND
                    nvl(creation_time, MINDATEVAL) < untilTime AND
                    drop_time > untilTime)) OR
           ((untilSCN is not null) AND not exists
            (SELECT 1
               FROM rc_datafile
              WHERE dbinc_key = this_dbinc_key AND
                    name = translateDatafilename.fileName AND
                    creation_change# < untilSCN AND
                    drop_change# > untilSCN)));
-- Translate a datafile number
-- Note: inBackup field has value 1 if included_in_database_backup is 'YES'
CURSOR translateDatafileNumber(
   fno  number)
RETURN dfRec_t IS
   SELECT file#, creation_change#, creation_time,
          name, tablespace_name, ts#,
          null, blocks, block_size, bytes / 1024,
          null, stop_change#, read_only, rfile#,
          decode(included_in_database_backup, 'YES', 1, 0),
          aux_name
     FROM rc_datafile
    WHERE db_key = this_db_key AND              -- belongs to this database
          file# = translateDataFileNumber.fno AND       -- filenumber matches
          dbinc_key = this_dbinc_key AND
          ((untilSCN is null AND drop_change# is null) OR
           ((nvl(creation_time, MINDATEVAL) < untilTime OR
             creation_change# < untilSCN) AND
            (drop_time > untilTime OR
             drop_change# > untilSCN OR
             drop_change# is null)));
-- Translate a datafile number and checkpoint SCN
-- Note: inBackup field has value 1 if included_in_database_backup is 'YES'
CURSOR translateDatafileCheckpoint(
   fno          number
  ,ckpSCN       number)
RETURN dfRec_t IS
   SELECT file#, creation_change#, creation_time,
          name, tablespace_name, ts#,
          null, blocks, block_size, bytes / 1024,
          null, stop_change#, read_only, rfile#,
          decode(included_in_database_backup, 'YES', 1, 0),
          aux_name
     FROM rc_datafile
    WHERE db_key = this_db_key                  -- belongs to this database
      AND file# = translateDatafileCheckpoint.fno       -- filenumber matches
      AND dbinc_key = this_dbinc_key
      AND translateDatafileCheckpoint.ckpSCN >= creation_change#
      AND (drop_change# IS NULL OR
           translateDatafileCheckpoint.ckpSCN < drop_change#);
-- Translate all datafiles that ever existed
-- Note that we return nulls for most fields here.  This is because
-- the controlfile version of this cursor has to return nulls for them
-- because it doesn't have the information, and so we return nulls here
-- so that things are consistant.
-- We assume that if a datafile was added and backed up, then a resync
-- was done before the datafile was dropped.  RMAN could not have created
-- the backup otherwise.
-- Note: inBackup field has value 1 if included_in_database_backup is 'YES'
CURSOR translateAllDatafile_c
RETURN dfRec_t IS
   SELECT DISTINCT
          file#                 dfNumber,
          creation_change#      dfCreationSCN,
          creation_time         dfCreationTime,
          name                  fileName,
          tablespace_name       tsName,
          ts#                   tsNumber,
          to_char(null)         status,
          blocks                blocks,
          block_size            blockSize,
          bytes / 1024          kbytes,
          to_number(null)       unrecovSCN,
          stop_change#          stopSCN,
          FALSE#                readOnly,
          rfile#                rfNumber,
          decode(included_in_database_backup, 'YES', 1, 0)
                                inBackup,
          aux_name              auxNAme
     FROM rc_datafile
    WHERE db_key = this_db_key
    ORDER BY file#;
-- Translate all datafiles in rc_database_block_corruption
-- Note: inBackup field has value 1 if included_in_database_backup is 'YES'
CURSOR translateCorruptList_c
RETURN dfRec_t IS
   SELECT DISTINCT
          rcd.file#, rcd.creation_change#, rcd.creation_time,
          rcd.name, rcd.tablespace_name, rcd.ts#,
          null, rcd.blocks, rcd.block_size, rcd.bytes / 1024,
          null, rcd.stop_change#, rcd.read_only, rcd.rfile#,
          decode(rcd.included_in_database_backup, 'YES', 1, 0),
          aux_name
     FROM rc_datafile rcd,
          (select distinct file# from rc_database_block_corruption) bc
    WHERE rcd.db_key = this_db_key AND          -- belongs to this database
          rcd.file# = bc.file# AND              -- filenumber matches
          rcd.dbinc_key = this_dbinc_key AND
          ((untilSCN is null AND rcd.drop_change# is null) OR
           ((nvl(rcd.creation_time, MINDATEVAL) < untilTime OR
             rcd.creation_change# < untilSCN) AND
            (rcd.drop_time > untilTime OR
             rcd.drop_change# > untilSCN OR
             rcd.drop_change# is null)));
----------------------------
-- Online Log Translation --
----------------------------
CURSOR translateOnlineLogs_c IS
   SELECT thread#, group#, name
     FROM rc_redo_log
    WHERE dbinc_key = this_dbinc_key
    ORDER BY thread#, group#, name;
------------------------------
-- Archived Log Translation --
------------------------------
getArchivedLogNoRows            noRows_t;
getArchivedLogDuplicates        number;         -- Duplicate filtering flag
getArchivedLogLast              alRec_t;        -- used for duplicate filtering
getArchivedLogCursor            varchar2(40);
CURSOR translateArcLogKey(
   alKey        IN     number
  ,needstby     IN     number DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          recid,
          stamp,
          thread#,
          sequence#,
          name,
          first_change#,
          first_time,
          next_change#,
          next_time,
          resetlogs_change#,
          resetlogs_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM rc_archived_log
    WHERE db_key = this_db_key
      AND (needstby is NULL OR
           nvl(is_standby, 'NO') = decode(needstby, TRUE#, 'YES', 'NO'))
      AND al_key = translateArcLogKey.alKey;
CURSOR translateArcLogName(
   fname        IN varchar2
  ,statusMask   IN binary_integer
  ,online       IN number                       -- IGNORED!
  ,needstby     IN number  DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          recid,
          stamp,
          thread#,
          sequence#,
          name,
          first_change#,
          first_time,
          next_change#,
          next_time,
          resetlogs_change#,
          resetlogs_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM rc_archived_log
    WHERE db_key = this_db_key
      AND name = translateArcLogName.fname
      AND isStatusMatch(status,statusMask) = TRUE#
      AND archived = 'YES'
      AND (needstby is NULL OR
           nvl(is_standby, 'NO') = decode(needstby, TRUE#, 'YES', 'NO'))
    ORDER BY stamp desc;
CURSOR translateArcLogSeqRange(
   thread#      IN number
  ,fromseq#     IN number
  ,toseq#       IN number
  ,pattern      IN varchar2
  ,statusMask   IN binary_integer
  ,online       IN number                       -- IGNORED!
  ,needstby     IN number  DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          recid,
          stamp,
          thread#,
          sequence#,
          name,
          first_change#,
          first_time,
          next_change#,
          next_time,
          resetlogs_change#,
          resetlogs_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM rc_archived_log
    WHERE dbinc_key = this_dbinc_key
      AND thread# = translateArcLogSeqRange.thread#
      AND sequence# between nvl(fromseq#, 0)
                        and nvl(toseq#, MAXSEQVAL)
      AND name is not null              -- filter out cleared logs
      AND (pattern is null OR name like pattern)
      AND isstatusMatch(status,statusMask) = TRUE#
      AND archived = 'YES'
      AND (needstby is NULL OR
           nvl(is_standby, 'NO') = decode(needstby, TRUE#, 'YES', 'NO'))
    ORDER BY thread#, first_change#, sequence#, stamp desc;
CURSOR translateArcLogSeqRange2(
   thread#      IN number
  ,fromseq#     IN number
  ,toseq#       IN number
  ,needstby     IN number  DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          recid,
          stamp,
          thread#,
          sequence#,
          name,
          first_change#,
          first_time,
          next_change#,
          next_time,
          resetlogs_change#,
          resetlogs_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM rc_archived_log
    WHERE dbinc_key = this_dbinc_key
      AND thread# = translateArcLogSeqRange2.thread#
      AND sequence# between nvl(fromseq#, 0)
                        and nvl(toseq#, MAXSEQVAL)
      AND name is not null              -- filter out cleared logs
      AND archived = 'YES'
      AND (needstby is NULL OR
           nvl(is_standby, 'NO') = decode(needstby, TRUE#, 'YES', 'NO'))
    UNION ALL
   SELECT to_number(null),
          to_number(null),
          -1,                                   -- to sort last (desc)
          thread#,
          sequence#,
          to_char(null),
          low_scn,
          low_time,
          next_scn,
          next_time,
          reset_scn,
          reset_time,
          blocks,
          block_size,
          'D',
          to_date(null),
          0
     FROM brl, dbinc
    WHERE brl.dbinc_key = dbinc.dbinc_key       -- join condition
      AND brl.dbinc_key = this_dbinc_key
      AND thread# = translateArcLogSeqRange2.thread#
      AND sequence# between nvl(fromseq#, 0)
                        and nvl(toseq#, MAXSEQVAL)
       --    thread#, low_scn, al_stamp desc
    ORDER BY       4,       7,        3 desc;
CURSOR translateArcLogTimeRange(
   thread#      IN number
  ,fromTime     IN date
  ,toTime       IN date
  ,pattern      IN varchar2
  ,statusMask   IN binary_integer
  ,online       IN number               -- IGNORED!
  ,needstby     IN number   DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          al_recid,
          al_stamp,
          thread#,
          sequence#,
          fname,
          low_scn,
          low_time,
          next_scn,
          next_time,
          reset_scn,
          reset_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM al, dbinc
    WHERE al.dbinc_key = this_dbinc_key
      AND dbinc.dbinc_key = this_dbinc_key
      AND (translateArcLogTimeRange.thread# is NULL OR
           thread# = translateArcLogTimeRange.thread#)
      AND next_time >  nvl(fromTime, MINDATEVAL)
      AND low_time  <= nvl(toTime, MAXDATEVAL)
      AND fname is not null             -- filter out cleared logs
      AND (pattern is null OR fname like pattern)
      AND isStatusMatch(status,statusMask) = TRUE#
      AND archived = 'Y'
      AND (needstby is NULL OR
           nvl(is_standby, 'N') = decode(needstby, TRUE#, 'Y', 'N'))
    ORDER BY thread#, low_scn, sequence#, al_stamp desc;
CURSOR translateArcLogTimeRange2(
   thread#      IN number
  ,fromTime     IN date
  ,toTime       IN date
  ,needstby     IN number   DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          al_recid,
          al_stamp,
          thread#,
          sequence#,
          fname,
          low_scn,
          low_time,
          next_scn,
          next_time,
          reset_scn,
          reset_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM al, dbinc
    WHERE al.dbinc_key = this_dbinc_key
      AND dbinc.dbinc_key = this_dbinc_key
      AND (translateArcLogTimeRange2.thread# is NULL OR
           thread# = translateArcLogTimeRange2.thread#)
      AND next_time >  nvl(fromTime, MINDATEVAL)
      AND low_time  <= nvl(toTime, MAXDATEVAL)
      AND fname is not null             -- filter out cleared logs
      AND archived = 'Y'
      AND (needstby is NULL OR
           nvl(is_standby, 'N') = decode(needstby, TRUE#, 'Y', 'N'))
    UNION ALL
   SELECT to_number(null),
          to_number(null),
          -1,                                   -- to sort last
          thread#,
          sequence#,
          to_char(null),
          low_scn,
          low_time,
          next_scn,
          next_time,
          reset_scn,
          reset_time,
          blocks,
          block_size,
          'D',
          to_date(null),
          0
     FROM brl, dbinc
    WHERE brl.dbinc_key = dbinc.dbinc_key       -- join condition
      AND brl.dbinc_key = this_dbinc_key
      AND next_time >  nvl(fromTime, MINDATEVAL)
      AND low_time  <= nvl(toTime, MAXDATEVAL)
      AND (translateArcLogTimeRange2.thread# is NULL OR
           thread# = translateArcLogTimeRange2.thread#)
       --    thread#, low_scn, al_stamp desc
    ORDER BY       4,       7,        3 desc;
-- This is the only cursor that respects the online parameter.
CURSOR translateArcLogSCNRange(
   thread#      IN number
  ,fromSCN      IN number
  ,toSCN        IN number
  ,pattern      IN varchar2
  ,statusMask   IN binary_integer
  ,online       IN number
  ,needstby     IN number  DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          al_recid,
          al_stamp,
          thread#,
          sequence#,
          fname,
          low_scn,
          low_time,
          next_scn,
          next_time,
          reset_scn,
          reset_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM al, dbinc
    WHERE al.dbinc_key = this_dbinc_key
      AND dbinc.dbinc_key = this_dbinc_key
      AND (translateArcLogSCNRange.thread# is NULL OR
           thread# = translateArcLogSCNRange.thread#)
      AND next_scn > nvl(fromSCN, 0)
      AND low_scn  < nvl(toSCN, MAXSCNVAL)
      AND fname is not null             -- filter out cleared logs
      AND (pattern is null OR fname like pattern)
      AND isStatusMatch(status,statusMask) = TRUE#
      AND ("ONLINE" = 1 OR archived = 'Y')
      AND (needstby is NULL OR
           nvl(is_standby, 'N') = decode(needstby, TRUE#, 'Y', 'N'))
    ORDER BY thread#, low_scn, al_stamp desc;
-- This cursor is used by krmkdmr().  krmkdmr() uses
-- this to get all archivelogs in the SCN range (x..infinity) where x
-- is the SCN where  media recovery first requests a log.  This is the only
-- cursor that respects the online parameter.  Note that if we have
-- an inspected current online log in the list, then either that log has never
-- been archived, or if it has been archived, then the archived record has
-- a higher stamp, so the order by stamp desc means the archived copy
-- is returned first.
-- We union the al table with the brl table because
-- an archivedlog in the SCN range may have had its al record deleted or
-- uncataloged, but we still have a backup of that log.  We could instead/also
-- union with rc_log_history, but if that gives us a log we wouldn't otherwise
-- see, then we will fail anyway since there is no copy or backup of that log.
-- As it is, we will give a meaningful error message if recovery asks for a log
-- we don't have, so there is no need to look at the log_history.
CURSOR translateArcLogSCNRange2(
   thread#      IN number
  ,fromSCN      IN number
  ,toSCN        IN number
  ,toTime       IN date
  ,needstby     IN number  DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          al_recid,
          al_stamp,
          thread#,
          sequence#,
          fname,
          low_scn,
          low_time,
          next_scn,
          next_time,
          reset_scn,
          reset_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM al, dbinc
    WHERE al.dbinc_key = this_dbinc_key
      AND dbinc.dbinc_key = this_dbinc_key
      AND (translateArcLogSCNRange2.thread# is NULL OR
           thread# = translateArcLogSCNRange2.thread#)
      AND next_scn > nvl(fromSCN, 0)
      AND low_scn  < nvl(toSCN, MAXSCNVAL)
      AND (toTime IS NULL OR low_time < toTime)
      AND (needstby is NULL OR
           nvl(is_standby, 'N') = decode(needstby, TRUE#, 'Y', 'N'))
    UNION ALL
   SELECT to_number(null),
          to_number(null),
          -1,                                   -- to sort last
          thread#,
          sequence#,
          to_char(null),
          low_scn,
          low_time,
          next_scn,
          next_time,
          reset_scn,
          reset_time,
          blocks,
          block_size,
          'D',
          to_date(null),
          0
     FROM brl, dbinc
    WHERE brl.dbinc_key = dbinc.dbinc_key       -- join condition
      AND brl.dbinc_key = this_dbinc_key
      AND (translateArcLogSCNRange2.thread# is NULL OR
           thread# = translateArcLogSCNRange2.thread#)
      AND next_scn > nvl(fromSCN, 0)
      AND low_scn  < nvl(toSCN, MAXSCNVAL)
      AND (toTime IS NULL OR low_time < toTime)
       --    thread#, low_scn, al_stamp desc;
    ORDER BY       4,       7,        3 desc;
CURSOR translateArcLogPattern(
   pattern      IN varchar2
  ,statusMask   IN binary_integer
  ,online       IN number                       -- IGNORED!
  ,needstby     IN number   DEFAULT NULL)
RETURN alRec_t IS
   SELECT al_key,
          recid,
          stamp,
          thread#,
          sequence#,
          name,
          first_change#,
          first_time,
          next_change#,
          next_time,
          resetlogs_change#,
          resetlogs_time,
          blocks,
          block_size,
          status,
          completion_time,
          0
     FROM rc_archived_log
    WHERE dbinc_key = this_dbinc_key
      AND (pattern is null or name like pattern)
      AND isStatusMatch(status,statusMask) = TRUE#
      AND archived = 'YES'
      AND (needstby is NULL OR
           nvl(is_standby, 'NO') = decode(needstby, TRUE#, 'YES', 'NO'))
    ORDER BY thread#, first_change#, sequence#, stamp desc;
---------------------------------
-- Controlfilecopy Translation --
---------------------------------
getControlFileCopySingleRow     boolean;
---------------------
-- getDatafileCopy --
---------------------
getDatafileCopyCursor           varchar2(30);
getDatafileCopyNoRows           noRows_t;
getDatafileCopyDuplicates       number;
getDatafileCopyLast             rcvRec_t;
getDatafileCopySingleRow        boolean;
------------------
-- getProxyCopy --
------------------
getProxyCopyCursor              varchar2(30);
getProxyCopyNoRows              noRows_t;
getProxyCopyByHandle            boolean;
--------------------
-- getBackupPiece --
--------------------
getBackupPieceCursor            varchar2(30);
getBackupPieceNoRows            noRows_t;
getBackupPieceDuplicates        number; -- TRUE# -> duplicates OK
                                        -- FALSE# -> eliminate duplicates
getBackupPieceLast              bpRec_t;
-- getBackupPieceDeviceType must not be null if getBackupPieceDuplicates
-- is FALSE#.
getBackupPieceDeviceType        bp.device_type%TYPE;
getBackupPieceExpectedPieces    number;
getBackupPiecePieceCount        number;
getBackupPieceByHandle          boolean;
getBackupPieceAvailableMask     binary_integer;
----------
-- List --
----------
listGetBackupTag                bp.tag%TYPE;
listGetBackupAvailableMask      binary_integer;
listGetProxyDatafileCursor      varchar2(30);
-- This cursor is just a bad idea.  It is here only for backward
-- compatibility with 8.1.
CURSOR lbal2(thread#       number,
             lowseq        number,
             highseq       number,
             lowscn        number,
             highscn       number,
             from_time     date  ,
             until_time    date)
RETURN rcvRec_t IS
   SELECT backupSet_con_t       type_con,
          brl.brl_key           key_con,
          brl.brl_recid         recid_con,
          brl.brl_stamp         stamp_con,
          bs.set_stamp          setStamp_con,
          bs.set_count          setCount_con,
          bs.bs_recid           bsRecid_con,
          bs.bs_stamp           bsStamp_con,
          bs.bs_key             bsKey_con,
          to_number(null)       bsLevel_con,
          bs.bck_type           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                elapseSecs_con,
          bs.pieces             pieceCount_con,
          to_char(null)         fileName_con,
          to_char(null)         tag_con,
          to_number(null)       copyNumber_con,
          to_char(null)         status_con,
          brl.blocks            blocks_con,
          brl.block_size        blockSize_con,
          to_char(null)         deviceType_con,
          bs.completion_time    compTime_con,
          to_date(null)         cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          to_number(null)       fromSCN_act,
          to_number(null)       toSCN_act,
          to_date(null)         toTime_act,
          to_number(null)       rlgSCN_act,
          to_date(null)         rlgTime_act,
          dbinc.dbinc_key       dbincKey_act,
          to_number(null)       level_act,
          to_number(null)       dfNumber_obj,
          to_number(null)       dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          brl.sequence#         logSequence_obj,
          brl.thread#           logThread_obj,
          dbinc.reset_scn       logRlgSCN_obj,
          dbinc.reset_time      logRlgTime_obj,
          brl.low_scn           logLowSCN_obj,
          brl.low_time          logLowTime_obj,
          brl.next_scn          logNextSCN_obj,
          brl.next_time         logNextTime_obj,
          to_number(null)       keep_options,
          to_date(null)         keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
  from  brl, bs, dbinc
  where dbinc.db_key    = this_db_key      -- this database
  and   dbinc.dbinc_key = brl.dbinc_key    -- join dbinc, brl
  and   bs.bs_key       = brl.bs_key       -- join bs, brl
  and  (lbal2.thread# is null or brl.thread# = lbal2.thread#)
  and  (brl.sequence# between nvl(lbal2.lowseq, 0)
                     and     nvl(lbal2.highseq, MAXSEQVAL))
  and  (lowscn        is null or brl.low_scn >= lowscn)
  and  (highscn       is null or brl.next_scn<  highscn)
  and  (from_time     is null or bs.completion_time >= from_time)
  and  (until_time    is null or bs.completion_time <= until_time)
--and  (pattern       is null or brl.name like pattern)
  and   bs.status != 'D'
  order by bs.bs_key, brl.thread#, brl.sequence#;
CURSOR ldbi(
   db_name varchar2)
IS
   SELECT db_key, dbinc_key, name, dbid, current_incarnation,
          resetlogs_change#, resetlogs_time
     FROM rc_database_incarnation
    WHERE (ldbi.db_name IS NULL OR
           name = upper(ldbi.db_name))
    ORDER BY dbid, resetlogs_change#;
CURSOR lrtbs
IS
   SELECT DISTINCT ts.ts#, ts.ts_name
     FROM ts, tsatt, ckp ckp1, ckp ckp2
      -- Join ts to tsatt by dbinc_key, ts#, creation_scn
    WHERE ts.dbinc_key  = tsatt.dbinc_key
      AND ts.ts#        = tsatt.ts#
      AND ts.create_scn = tsatt.create_scn
      -- Join tsatt to the ckp row containing the first SCN where we know that
      -- these tsatt values are valid.  tsatt.start_ckp_key is never null.
      AND ckp1.ckp_key = tsatt.start_ckp_key
      -- Join tsatt to the ckp row containing an SCN beyond which we know that
      -- these tsatt values are not valid.  Do an outer join because
      -- tsatt.end_ckp_key can be null.
      AND ckp2.ckp_key(+) = tsatt.end_ckp_key
      -- Select only rows belonging to the current incarnation.
      AND ts.dbinc_key = this_dbinc_key
      -- If there is an until SCN, select only tablespaces created earlier.
      -- If there is no until SCN, let the row pass (it will be filtered by
      -- the next condition if it has been dropped).  create_scn is never null.
      AND (ts.create_scn < untilSCN or untilSCN is NULL)
      -- Select rows for tablespaces that have never been dropped, or which
      -- were dropped more recently than the until SCN.  If there is a
      -- drop_scn and no until SCN (which means we don't want this row),
      -- then both conditions are false (NULL always compares false, and
      -- drop_scn is not null).
      AND (ts.drop_scn > untilSCN or ts.drop_scn is NULL)
      -- If there is an until SCN, select only those rows where we know that
      -- the tsatt values were valid at or before that SCN.  ckp1.ckp_scn is
      -- never null.  If there is no until SCN, let the row pass (it will be
      -- filtered by the next condition if the tsatt values are no longer
      -- valid).
      AND (ckp1.ckp_scn <= untilSCN or untilSCN is NULL)
      -- Select only those rows for which the tsatt values are still valid, or
      -- were known to be valid AFTER the until SCN.  If there is no until SCN
      -- and the tsatt values are no longer valid (which means we don't want
      -- this row), then both conditions will be false.
      AND (ckp2.ckp_scn > untilSCN or ckp2.ckp_scn is NULL)
      -- All that was just to get us here.  Select only tablespaces which
      -- contain one or more rollback segments.
      AND tsatt.rbs_count > 0
    ORDER BY 1;
-------------------------------------------------------
-- listTranslateProxyDFRecid and translateBackupFile --
-------------------------------------------------------
rcvRec_last     rcvRec_t;                       -- last record returned from:
                                                -- getRecoveryAction
                                                -- findControlFileBackup
-------------------------
-- getOfflineRangeCopy --
-------------------------
CURSOR getOfflineRangeCopy_c(
   offrRecid    number
  ,offrCkpSCN   number
  ,cfCreTime    date
  ,dbincKey     number)
RETURN rcvRec_t IS
   SELECT imageCopy_con_t       type_con,
          ccf_key               key_con,
          ccf_recid             recid_con,
          ccf_stamp             stamp_con,
          to_number(null)       setStamp_con,
          to_number(null)       setCount_con,
          to_number(null)       bsRecid_con,
          to_number(null)       bsStamp_con,
          to_number(null)       bsKey_con,
          to_number(null)       bsLevel_con,
          to_char(null)         bsType_con,
          to_number(null)       elapseSecs_con,
          to_number(null)       pieceCount_con,
          fname                 fileName_con,
          tag                   tag_con,
          to_number(null)       copyNumber_con,
          status                status_con,
          to_number(null)       blocks_con,     -- ccf doesn't have blocks
          block_size            blockSize_con,
          'DISK'                deviceType_con,
          completion_time       compTime_con,
          create_time           cfCreationTime_con,
          to_number(null)       pieceNumber_con,
          to_date(null)         bpCompTime_con,
          full_act_t            type_act,
          0                     fromSCN_act,
          ccf.ckp_scn           toSCN_act,
          ccf.ckp_time          toTime_act,
          dbinc.reset_scn       rlgSCN_act,
          dbinc.reset_time      rlgTime_act,
          ccf.dbinc_key         dbincKey_act,
          to_number(null)       level_act,
          0                     dfNumber_obj,
          0                     dfCreationSCN_obj,
          to_number(null)       cfSequence_obj,
          to_date(null)         cfDate_obj,
          to_number(null)       logSequence_obj,
          to_number(null)       logThread_obj,
          to_number(null)       logRlgSCN_obj,
          to_date(null)         logRlgTime_obj,
          to_number(null)       logLowSCN_obj,
          to_date(null)         logLowTime_obj,
          to_number(null)       logNextSCN_obj,
          to_date(null)         logNextTime_obj,
          ccf.keep_options      keep_options,
          ccf.keep_until        keep_until,
          to_number(null)       afzSCN_act,
          to_date(null)         rfzTime_act,
          to_number(null)       rfzSCN_act
     FROM ccf, dbinc
    WHERE dbinc.dbinc_key = getOfflineRangeCopy_c.dbincKey
      AND dbinc.dbinc_key = ccf.dbinc_key
      AND getOfflineRangeCopy_c.cfCretime = create_time
      AND getOfflineRangeCopy_c.offrCkpSCN < ccf.ckp_scn
      AND getOfflineRangeCopy_c.offrRecid >= min_offr_recid
      AND status = 'A'
    ORDER BY stamp_con desc;
-- list all backups/copies/offline-ranges for all datafiles,
-- for REPORT OBSOLETE
cursor rddf is
  -- datafile copies
  select 2 preference,
         file#, COPY filetype, checkpoint_change#, checkpoint_time,
         resetlogs_change#, resetlogs_time, 0 incremental_change#,
         decode(decode(online_fuzzy,'NO',0,1)+decode(backup_fuzzy,'NO',0,1),
            0,greatest(nvl(absolute_fuzzy_change#,0),
                       nvl(recovery_fuzzy_change#,0)),
            maxscnval) fuzzy_change#,
            recid, stamp, name, 0 set_stamp, 0 set_count, cdf_key key,
            completion_time, 'DISK' device_type
  from rc_datafile_copy
  where db_key = this_db_key
  and   status != 'D'
  union all
  -- proxy datafile copies
  select 3,
         file#, PROXY, checkpoint_change#, checkpoint_time,
         resetlogs_change#, resetlogs_time, 0,
         decode(decode(online_fuzzy,'NO',0,1)+decode(backup_fuzzy,'NO',0,1),
            0,greatest(nvl(absolute_fuzzy_change#,0),
                       nvl(recovery_fuzzy_change#,0)),
            maxscnval),
            recid, stamp, handle, 0, 0, xdf_key, completion_time, device_type
  from rc_proxy_datafile
  where db_key = this_db_key
  and   status != 'D'
  union all
  -- datafiles in backup sets
  select decode(bs.bck_type, 'D', 4,
                             'I', 5),
         file#,
         decode(bs.bck_type, 'D', FULL_DF_BACKUP,
                             'I', INCREMENTAL_DF_BACKUP),
         bdf.ckp_scn, bdf.ckp_time,
         dbinc.reset_scn, dbinc.reset_time, bdf.incr_scn,
         nvl(bdf.abs_fuzzy_scn,0),
         bs.bs_recid, bs.bs_stamp, null, bs.set_stamp, bs.set_count, bs.bs_key,
         bs.completion_time, null
  from bdf, bs, dbinc
  where dbinc.db_key    = this_db_key          -- this database
  and   dbinc.dbinc_key = bdf.dbinc_key        -- join dbinc, bdf
  and   bdf.bs_key      = bs.bs_key            -- join bdf, bs
  and   bs.status      != 'D'
  union all
  -- controlfile copies
  select 2,
         0, COPY, checkpoint_change#, checkpoint_time,
         resetlogs_change#, resetlogs_time, 0, 0, recid, stamp, name, 0, 0,
         ccf_key, completion_time, 'DISK'
  from rc_controlfile_copy
  where db_key = this_db_key
  and   status != 'D'
  union all
  -- proxy controlfile copies
  select 3,
         0, PROXY, checkpoint_change#, checkpoint_time,
         resetlogs_change#, resetlogs_time, 0, 0, recid, stamp, handle, 0, 0,
         xcf_key, completion_time, device_type
  from rc_proxy_controlfile
  where db_key = this_db_key
  and   status != 'D'
  union all
  -- controlfiles in backup sets
  select 4,
         0, FULL_DF_BACKUP,
         bcf.ckp_scn, bcf.ckp_time, dbinc.reset_scn, dbinc.reset_time,
         0, 0, bs.bs_recid, bs.bs_stamp, null,
         bs.set_stamp, bs.set_count, bs.bs_key, bs.completion_time, null
  from bcf, bs, dbinc
  where dbinc.db_key = this_db_key              -- this database
  and   dbinc.dbinc_key = bcf.dbinc_key         -- join dbinc, bcf
  and   bcf.bs_key = bs.bs_key                  -- join bcf, bs
  and   bs.status != 'D'
  union all
  -- offline ranges
  select 1,
         file#, OFFLINE_RANGE, online_change#, online_time,
         resetlogs_change#, resetlogs_time, offline_change#, 0,
         recid, stamp, null, 0, 0, 0, online_time, null
  from rc_offline_range ofr, rc_database_incarnation di
  where ofr.db_key = this_db_key
  and   di.db_key = this_db_key
  and   ofr.dbinc_key = di.dbinc_key
  -- The algorithm in krmkcofl (Construct Obsolete File List) depends on the
  -- following ordering.
  order by 2 asc,  -- file#
           4 desc, -- checkpoint_change#
           1 asc,  -- preference
          15 desc; -- completion_time, to break ties if all else is equal
----------------
-- BMR cursor --
----------------
-- to add row in corruption table to BMR list-
CURSOR bmrAddCorruptTable_c
IS
   SELECT DISTINCT
          file#, block#, blocks
     FROM rc_database_block_corruption bc
    WHERE bc.db_key = this_db_key AND           -- belongs to this database
          bc.dbinc_key = this_dbinc_key;
------------------------
-- RMAN configuration --
------------------------
CURSOR findConfig_c(
   name varchar2,
   value varchar2)
IS
    SELECT conf#, name, value
    FROM   rc_rman_configuration rm
    WHERE  db_key = this_db_key                  -- part of this database
    AND    ((findConfig_c.name is null OR
             UPPER(findConfig_c.name) = UPPER(rm.name)) AND
            (findConfig_c.value is null OR
             UPPER(findConfig_c.value) = UPPER(rm.value)));
--------------------
-- Backup History --
--------------------
getLastBackupHistory bhistoryRec_t;
CURSOR dfBackupHistory_c(
   file#       IN   number
  ,crescn      IN   number
  ,reset_scn   IN   number
  ,reset_time  IN   date)
RETURN bhistoryRec_t IS
   SELECT
      bs.bs_key                key,
      bp.device_type           device_type,
      bdf.file#                dfNumber,
      bdf.create_scn           create_scn,
      dbinc.reset_scn          reset_scn,
      dbinc.reset_time         reset_time,
      bdf.ckp_scn              ckp_scn,
      nvl(df.stop_scn, 0)      stop_scn,
      to_number(null)          logThread,
      to_number(null)          logSequence,
      to_number(null)          setStamp,
      to_number(null)          setCount,
      max(bs.completion_time)  compTime,
      0                        nbackups
   FROM bdf,
        bs,
        bp,
        dbinc,
        df
   WHERE bdf.dbinc_key  = dbinc.dbinc_key       -- join dbinc, bdf
     AND dbinc.db_key   = this_db_key           -- this database
     AND bdf.create_scn = df.create_scn         -- create scn match
     AND bdf.file#      = df.file#              -- join bdf, df
     AND (dfBackupHistory_c.file# IS NULL OR
          df.file# = dfBackupHistory_c.file#)
     AND (dfBackupHistory_c.crescn IS NULL OR
          df.create_scn = dfBackupHistory_c.crescn)
     AND (dfBackupHistory_c.reset_scn IS NULL OR
          (dbinc.reset_scn = dfBackupHistory_c.reset_scn AND
           dbinc.reset_time = dfBackupHistory_c.reset_time))
     AND bdf.bs_key     = bs.bs_key             -- join bdf, bs
     AND bdf.bs_key     = bp.bs_key             -- join bdf, bp
     AND bs.status = 'A'                        -- available backupset
   GROUP BY bs.bs_key, bp.device_type, bp.copy#, bdf.file#, bdf.create_scn,
            dbinc.reset_scn, dbinc.reset_time, bdf.ckp_scn, df.stop_scn,
            bs.pieces
   HAVING ((count(DISTINCT bp.piece#) = bs.pieces) AND
           (count(DISTINCT bp.device_type) = 1))
   UNION ALL
   SELECT
      xdf.xdf_recid            key,
      xdf.device_type          device_type,
      xdf.file#                dfNumber,
      xdf.create_scn           create_scn,
      dbinc.reset_scn          reset_scn,
      dbinc.reset_time         reset_time,
      xdf.ckp_scn              ckp_scn,
      nvl(df.stop_scn, 0)      stop_scn,
      to_number(null)          logThread,
      to_number(null)          logSequence,
      to_number(null)          setStamp,
      to_number(null)          setCount,
      max(xdf.completion_time) compTime,
      0                        nbackups
   FROM xdf,
        df,
        dbinc
   WHERE xdf.dbinc_key   = dbinc.dbinc_key         -- join xdf, dbinc
     AND dbinc.db_key    = this_db_key             -- this database
     AND df.dbinc_key    = this_dbinc_key          -- this incarnation files
     AND xdf.create_scn  = df.create_scn           -- create scn match
     AND xdf.file#       = df.file#                -- join xdf, df
     AND (dfBackupHistory_c.file# IS NULL OR
          dfBackupHistory_c.file# = df.file#)
     AND (dfBackupHistory_c.crescn IS NULL OR
          df.create_scn = dfBackupHistory_c.crescn)
     AND (dfBackupHistory_c.reset_scn IS NULL OR
          (dbinc.reset_scn = dfBackupHistory_c.reset_scn AND
           dbinc.reset_time = dfBackupHistory_c.reset_time))
     AND xdf.status      = 'A'                     -- available proxy al
   GROUP BY xdf.xdf_recid, xdf.device_type, xdf.file#, xdf.create_scn,
            dbinc.reset_scn, dbinc.reset_time, xdf.ckp_scn, df.stop_scn
   -- order is important to find number of backups and max completion time
   ORDER BY  3, -- file#
             7, -- ckp_scn
             8, -- stop_scn
             2, -- device_type
            13; -- completion time
CURSOR alBackupHistory_c(
   thread#    IN number,
   sequence#  IN number)
RETURN bhistoryRec_t IS
   SELECT
      bs.bs_key                key,
      bp.device_type           device_type,
      to_number(null)          dfNumber,
      to_number(null)          create_scn,
      dbinc.reset_scn          reset_scn,
      dbinc.reset_time         reset_time,
      to_number(null)          ckp_scn,
      to_number(null)          stop_scn,
      brl.thread#              logThread,
      brl.sequence#            logSequence,
      to_number(null)          setStamp,
      to_number(null)          setCount,
      max(bs.completion_time)  compTime,
      0                        nbackups
   FROM brl,
        bs,
        bp,
        al,
        dbinc
   WHERE dbinc.dbinc_key = this_dbinc_key          -- this incarnation
     AND brl.dbinc_key   = dbinc.dbinc_key         -- join brl, dbinc
     AND al.dbinc_key    = this_dbinc_key          -- this incarnation files
     AND brl.thread#     = al.thread#              -- join brl and al
     AND brl.sequence#   = al.sequence#
     AND (alBackupHistory_c.thread# IS NULL OR
          alBackupHistory_c.thread# = al.thread#)
     AND (alBackupHistory_c.sequence# IS NULL OR
          alBackupHistory_c.sequence# = al.sequence#)
     AND brl.bs_key      = bs.bs_key               -- join brl,bs
     AND brl.bs_key      = bp.bs_key               -- join brl,bp
     AND bs.status       = 'A'                     -- available backupset
   GROUP BY bs.bs_key, bp.device_type, bp.copy#, bs.pieces, brl.thread#,
            brl.sequence#, dbinc.reset_scn, dbinc.reset_time
   HAVING ((count(DISTINCT bp.piece#) = bs.pieces) AND
           (count(DISTINCT bp.device_type) = 1))
   -- order is important to find number of backups and max completion time
   ORDER BY brl.thread#, brl.sequence#, bp.device_type;
CURSOR bsBackupHistory_c(
   set_stamp   IN   number
  ,set_count   IN   number
  )
RETURN bhistoryRec_t IS
   SELECT
      bs.bs_key                 key,
      bp.device_type            device_type,
      to_number(null)           dfNumber,
      to_number(null)           create_scn,
      dbinc.reset_scn           reset_scn,
      dbinc.reset_time          reset_time,
      to_number(null)           ckp_scn,
      to_number(null)           stop_scn,
      to_number(null)           logThread,
      to_number(null)           logSequence,
      bs.set_stamp              setStamp,
      bs.set_count              setCount,
      max(bp.completion_time)   compTime,
      0                         nbackups
   FROM bp,
        bs,
        dbinc
   WHERE bp.db_key       = dbinc.db_key            -- join bp, dbinc
     AND dbinc.db_key    = this_db_key             -- this database
     AND bp.bs_key       = bs.bs_key               -- join bs, bp
     AND (bsBackupHistory_c.set_stamp IS NULL OR
          (bsBackupHistory_c.set_stamp = bs.set_stamp AND
           bsBackupHistory_c.set_count = bs.set_count))
     AND bp.status = 'A'
   GROUP BY bs.bs_key, bp.device_type, bs.set_stamp, bs.set_count,
            bs.pieces, bp.copy#, dbinc.reset_scn, dbinc.reset_time
   HAVING ((count(DISTINCT bp.piece#) = bs.pieces) AND
           (count(DISTINCT bp.status) = 1))
   -- order is important to find number of backups and max completion time
   ORDER BY bs.bs_key, bp.device_type;
--
-- Two ways to validateBackupSet.
-- o validateBackupSet() old way.
-- o qukvalidateBackupSet() will use in-memory records and is faster. Before
--   this call you should populate the in-memory records once using
--   createinCorebsRecStack
--
validateBackupSet_method  varchar2(30);  -- tell the way to validate backupSet
--
-- We will use this cursor in 10iR1 to make validBackupSet() faster.
-- For now, only getIncrementalScn uses this.
--
CURSOR inCorebsRec_c(
   backupType             IN     binary_integer
  ,tag                    IN     varchar2
  ,statusMask             IN     number
  ,completedAfter         IN     date
  ,completedBefore        IN     date)
RETURN inCorebsCursor_t IS
   SELECT bs.bs_key              bsKey,
          bs.set_stamp           setStamp,
          bs.set_count           setCount,
          bp.device_type         deviceType,
          bs.pieces              pieceCount
     FROM bp, bs
   WHERE (bs.db_key = this_db_key)      -- belongs to this database
     AND (bs.bs_key = bp.bs_key)        -- join bs and bp
     AND (isStatusMatch(bp.status, inCorebsRec_c.statusMask) = TRUE#)
     AND (inCorebsRec_c.backupType IS NULL OR
          isBackupTypeMatch(bs.bck_type, backupType) = TRUE#)
     AND (inCorebsRec_c.tag IS NULL OR
          inCorebsRec_c.tag = bp.tag)
     AND (completedAfter IS NULL OR bs.completion_time >= completedAfter)
     AND (completedBefore IS NULL OR bs.completion_time <= completedBefore)
   GROUP BY bs.bs_key, bs.set_stamp, bs.set_count, bp.device_type,
            bs.pieces
   HAVING ((bitand(statusMask, dbms_rcvman.BSpartial_avail) = 0 AND
            count(DISTINCT bp.piece#) = bs.pieces) OR
           (bitand(statusMask, dbms_rcvman.BSpartial_avail) <> 0 AND
            count(DISTINCT bp.piece#) <= bs.pieces))
   ORDER BY bs.bs_key;
------------------------------------------------
-- *** PRIVATE FUNCTION/PROCEDURE SECTION *** --
------------------------------------------------
---------------
-- Debugging --
---------------
------------------------------------- deb -------------------------------------
PROCEDURE deb(
   type IN number
  ,line IN varchar2 DEFAULT NULL
)
IS
    pname varchar2(50);
    pref varchar(11) := 'DBGRCVMAN: ';
    buffer_overflow exception;
    pragma exception_init(buffer_overflow, -20000);
BEGIN
   IF (not debug) THEN
      RETURN;
   END IF;
   IF type = DEB_ENTER THEN
      pname := line;
      dbms_output.put_line(pref||rpad(' ',pname_i)||'ENTERING '||pname);
      pname_i := pname_i + 1;
      last_pnames(pname_i) := pname;
   ELSIF type = DEB_IN THEN
      dbms_output.put_line(pref||rpad(' ',pname_i+2)||last_pnames(pname_i)||
                           ' '||line);
   ELSIF type = DEB_EXIT THEN
      IF (pname_i >= 1) THEN
          pname := last_pnames(pname_i);
          pname_i := pname_i - 1;
      ELSE
          pname := DEB_DEF_PNAME;
      END IF;
      IF line is not NULL THEN
         dbms_output.put_line(pref||rpad(' ', pname_i)||'EXITING '||pname||
                              ' '||line);
      ELSE
         dbms_output.put_line(pref||rpad(' ', pname_i)||'EXITING '||pname);
      END IF;
   ELSIF type = DEB_OPEN THEN
      pname := last_pnames(pname_i);
      dbms_output.put_line(pref||rpad(' ', pname_i)||'OPENING cursor '||
                           line||' in '||pname);
   ELSE
      dbms_output.put_line(pref||line);
   END IF;
EXCEPTION
   WHEN buffer_overflow THEN
      -- More debug information printed in this session to exceed buffer limit.
      -- dbms_output doesn't provide a way to flush current buffer.
      -- Just continue by disable and enable it again. We have lost previous
      -- debug information.
      dbms_output.disable;
      dbms_output.enable(1000000);
   WHEN others THEN
      dbms_output.put_line('caught exception during deb ' ||
                           substr(sqlerrm, 1, 512));
END;
FUNCTION bool2char(
   flag IN boolean)
RETURN varchar2 IS
BEGIN
   IF (flag) THEN
      RETURN 'TRUE';
   ELSE
      RETURN 'FALSE';
   END IF;
END bool2char;
--------------------------
-- Database Translation --
--------------------------
-- Private procedure to check if a tablespace should be skipped.
-------------------------------- skipTableSpace -------------------------------
FUNCTION skipTableSpace(
   tsName IN varchar2)
RETURN boolean IS
BEGIN
   deb(DEB_ENTER, 'skipTableSpace');
   FOR i in 1..skipTablespaceCount LOOP
      IF (tsName = skipTablespaceList(i)) THEN
         deb(DEB_EXIT, 'with: TRUE');
         RETURN TRUE;
      END IF;
   END LOOP;
   deb(DEB_EXIT, 'with: FALSE');
   RETURN FALSE;
END;
------------------------------
-- Package State Validation --
------------------------------
-------------------------------- validateState --------------------------------
PROCEDURE validateState(
   anyCursor IN varchar2)
IS
BEGIN
   IF (this_db_key IS NULL) THEN
      raise_application_error(-20021, 'database not set');
   END IF;
   IF (this_dbinc_key IS NULL) THEN
      raise_application_error(-20020, 'Database incarnation not set');
   END IF;
   IF (anyCursor IS NOT NULL) THEN
      raise_application_error(-20203, 'Translation already started');
   END IF;
END;
---------------------
-- Query Filtering --
---------------------
-- Private procedure to find the highest SCN that is associated with a
-- timestamp less than or equal to timeStamp.  This will give us an
-- approximate untilSCN which we can use in the WHERE clause of the queries.
--
-- Scanning of v$datafile is done so that the name translation cursors
-- can rely on just the scnVar in their where clause.
--
-- Offline ranges are scanned so that ones whose online checkpoint time
-- is at or after the from time are skipped.
----------------------------- computeUntilSCN -------------------------------
PROCEDURE computeUntilSCN(
   timeStamp IN date
  ,scn       OUT number)
IS
   mySCN     number;
BEGIN
   deb(DEB_ENTER, 'computeUntilSCN');
   SELECT nvl(max(first_change#),0)
     INTO mySCN
     FROM rc_log_history
    WHERE dbinc_key = this_dbinc_key
      AND first_time <= timeStamp;
   SELECT greatest(nvl(max(low_scn), 0), mySCN)
     INTO mySCN
     FROM al
    WHERE dbinc_key = this_dbinc_key
      AND low_time <= timeStamp;
   SELECT greatest(nvl(max(checkpoint_change#),0), mySCN)
     INTO mySCN
     FROM rc_backup_datafile
    WHERE dbinc_key = this_dbinc_key
      AND checkpoint_time <= timeStamp;
   SELECT greatest(nvl(max(absolute_fuzzy_change#),0), mySCN)
     INTO mySCN
     FROM rc_backup_datafile
    WHERE dbinc_key = this_dbinc_key
      AND completion_time <= timeStamp;
   SELECT greatest(nvl(max(checkpoint_change#),0), mySCN)
     INTO mySCN
     FROM rc_backup_controlfile
    WHERE dbinc_key = this_dbinc_key
      AND checkpoint_time <= timeStamp;
   SELECT greatest(nvl(max(checkpoint_change#),0), mySCN)
     INTO mySCN
     FROM rc_datafile_copy
    WHERE dbinc_key = this_dbinc_key
      AND checkpoint_time <= timeStamp;
   SELECT greatest(nvl(max(absolute_fuzzy_change#),0), mySCN)
     INTO mySCN
     FROM rc_datafile_copy
    WHERE dbinc_key = this_dbinc_key
      AND completion_time <= timeStamp;
   SELECT greatest(nvl(max(recovery_fuzzy_change#),0), mySCN)
     INTO mySCN
     FROM rc_datafile_copy
    WHERE dbinc_key = this_dbinc_key
      AND recovery_fuzzy_time <= timeStamp;
   SELECT greatest(nvl(max(checkpoint_change#),0), mySCN)
     INTO mySCN
     FROM rc_controlfile_copy
    WHERE dbinc_key = this_dbinc_key
      AND checkpoint_time <= timeStamp;
   SELECT greatest(nvl(max(checkpoint_change#),0), mySCN)
     INTO mySCN
     FROM rc_proxy_datafile
    WHERE dbinc_key = this_dbinc_key
      AND checkpoint_time <= timeStamp;
   SELECT greatest(nvl(max(create_scn), 0), mySCN)
     INTO mySCN
     FROM df
    WHERE dbinc_key = this_dbinc_key
      AND create_time <= timeStamp;
   SELECT greatest(nvl(max(stop_scn), 0), mySCN)
     INTO mySCN
     FROM df
    WHERE dbinc_key = this_dbinc_key
      AND stop_time <= timeStamp;
   SELECT greatest(nvl(max(online_scn), 0), mySCN)
     INTO mySCN
     FROM offr
    WHERE dbinc_key = this_dbinc_key
      AND online_time <= timeStamp;
   scn := mySCN;
   deb(DEB_EXIT, 'with '||to_char(scn));
END computeUntilSCN;
---------------------------- isDeviceTypeAllocated ----------------------------
FUNCTION isDeviceTypeAllocated(
   deviceType IN varchar2)
RETURN NUMBER IS
BEGIN
   deb(DEB_ENTER, 'isDeviceTypeAllocated');
   IF (anyDevice) THEN
      deb(DEB_EXIT, 'with: TRUE#');
      RETURN TRUE#;
   END IF;
   FOR i IN 1..deviceCount LOOP
      IF deviceType = deviceList(i) THEN
         deb(DEB_EXIT, 'with: TRUE#');
         RETURN TRUE#;
      END IF;
   END LOOP;
   deb(DEB_EXIT, 'with: FALSE#');
   RETURN FALSE#;
END isDeviceTypeAllocated;
----------------------------
-- Backup Set Translation --
----------------------------
-- Lookup a backup set by primary key or recid/stamp
-------------------------------- findBackupSet --------------------------------
PROCEDURE findBackupSet(
   bsKey        IN     number DEFAULT NULL
  ,recid        IN     number DEFAULT NULL
  ,stamp        IN     number DEFAULT NULL
  ,bsRec        OUT    bsRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'findBackupSet');
   deb(DEB_IN, 'bsKey:'||nvl(bsKey, -1));
   IF (bsKey IS NOT NULL) THEN
      SELECT recid,
             stamp,
             bs_key,
             set_stamp,
             set_count,
             backup_type,
             incremental_level,
             elapsed_seconds,
             completion_time,
             status,
             pieces,
             decode (keep_options, 'LOGS'         , KEEP_LOGS
                                 , 'NOLOGS'       , KEEP_NOLOGS
                                 , 'CONSISTENT'   , KEEP_CONSIST
                                                  , KEEP_NO),
             keep_until
        INTO bsRec
        FROM rc_backup_set
       WHERE db_key = this_db_key
         AND findBackupSet.bsKey = bs_key;
   ELSE
      SELECT recid,
             stamp,
             bs_key,
             set_stamp,
             set_count,
             backup_type,
             incremental_level,
             elapsed_seconds,
             completion_time,
             status,
             pieces,
             decode (keep_options, 'LOGS'         , KEEP_LOGS
                                 , 'NOLOGS'       , KEEP_NOLOGS
                                 , 'CONSISTENT'   , KEEP_CONSIST
                                                  , KEEP_NO),
             keep_until
        INTO bsRec
        FROM rc_backup_set
       WHERE db_key = this_db_key
         AND findBackupSet.recid = recid
         AND findBackupSet.stamp = stamp;
   END IF;
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with error 20215');
      raise_application_error(-20215, 'Backup set is missing');
END findBackupSet;
---------------------------
-- Backup Set Validation --
---------------------------
---------------------------- computeAvailableMask -----------------------------
FUNCTION computeAvailableMask(
   available            IN number
  ,unavailable          IN number
  ,deleted              IN number
  ,expired              IN number
  ,partial_avail        IN number DEFAULT 0)
RETURN binary_integer IS
   rc           binary_integer := 0;
BEGIN
   deb(DEB_ENTER, 'computeAvailableMask');
   IF (available > 0) THEN
      rc := rc + dbms_rcvman.BSavailable;
   END IF;
   IF (unavailable > 0 ) THEN
      rc := rc + dbms_rcvman.BSunavailable;
   END IF;
   IF (deleted > 0 ) THEN
      rc := rc + dbms_rcvman.BSdeleted;
   END IF;
   IF (expired > 0 ) THEN
      rc := rc + dbms_rcvman.BSexpired;
   END IF;
   IF (partial_avail > 0 ) THEN
      rc := rc + dbms_rcvman.BSpartial_avail;
   END IF;
   deb(DEB_EXIT, 'with rc:'||to_char(rc));
   RETURN rc;
END computeAvailableMask;
-- Validate a backup set has all pieces available according the the specified
-- arguments.  Returns only 1 validBackupSetRec.  There may be other sets of
-- pieces that match the criteria.
------------------------------ findValidBackupSet -----------------------------
PROCEDURE findValidBackupSet(
   bsKey                IN     number
  ,pieceCount           IN     number
  ,deviceType           IN     varchar2 DEFAULT NULL
  ,tag                  IN     varchar2 DEFAULT NULL
  ,availableMask        IN     binary_integer)
IS
BEGIN
   deb(DEB_ENTER, 'findValidBackupSet');
   IF (pieceCount = 1) THEN
      IF (findValidBackupSet1P_c%ISOPEN) THEN
         CLOSE findValidBackupSet1P_c;
      END IF;
      -- NOTE!! NOTE!! NOTE!!
      -- We are aware the findValidBackupSet_c cursor doesn't scale
      -- when there are more backup pieces. So, let's for now optimize
      -- most case which is 1 piece in a backupset
      deb(DEB_OPEN, 'findValidBackupSet1P_c');
      OPEN findValidBackupSet1P_c(bsKey         => bsKey,
                                  pieceCount    => pieceCount,
                                  deviceType    => deviceType,
                                  tag           => tag,
                                  mask          => availableMask);
      getValidBackupSetCursor := 'findValidBackupSet1P_c';
   ELSE           -- more than one piece exists in this set
      IF (findValidBackupSet_c%ISOPEN) THEN
         CLOSE findValidBackupSet_c;
      END IF;
      deb(DEB_OPEN, 'findValidBackupSet_c');
      OPEN findValidBackupSet_c(bsKey         => bsKey,
                                pieceCount    => pieceCount,
                                deviceType    => deviceType,
                                tag           => tag,
                                mask          => availableMask);
      getValidBackupSetCursor := 'findValidBackupSet_c';
   END IF;
   deb(DEB_IN, 'bsKey=' || to_char(bsKey) || ' pieceCount=' ||
          to_char(pieceCount) ||' tag=' || nvl(tag, 'NULL'));
   deb(DEB_IN, ' deviceType=' || nvl(deviceType, 'NULL') ||
          ' mask=' || to_char(availableMask));
   getValidBackupSetLast.code       := 99;      -- init for getValidBackupSet
   deb(DEB_EXIT);
END findValidBackupSet;
------------------------------ validateBackupSet0 -----------------------------
FUNCTION validateBackupSet0(
   tag                     IN     varchar2 DEFAULT NULL
  ,tagMatchRequired        IN     boolean  DEFAULT TRUE
  ,checkDeviceIsAllocated  IN     boolean  DEFAULT TRUE
  ,validRec                OUT    validBackupSetRec_t)
RETURN binary_integer IS
   local        validBackupSetRec_t;
   rc           binary_integer;
   gotRecord    number;
BEGIN
   deb(DEB_ENTER, 'validateBackupSet0');
   <<validationLoop>>
   LOOP
      <<nextRow>>
      gotRecord := getValidBackupSet(validBackupSetRec      => local,
                                     checkDeviceIsAllocated => FALSE#);
      EXIT WHEN gotRecord = FALSE#;             -- cursor is closed already
      IF (checkDeviceIsAllocated) THEN
         IF (isDeviceTypeAllocated(local.deviceType) = FALSE#) THEN
            deb(DEB_IN, 'device is not allocated');
            -- The required deviceType is not allocated.  Remember that
            -- we found an available backup set though.
            IF (rc IS NULL OR rc <> SUCCESS) THEN
               deb(DEB_IN, 'set rc to available');
               rc := dbms_rcvman.AVAILABLE;
            END IF;
            GOTO nextRow;
         END IF;
      END IF;
      validRec := local;                        -- set OUT mode arg
      IF (tag IS NOT NULL AND NOT tagMatchRequired) THEN
         -- We are looking for backup sets with a particular tag, but
         -- we want to know about a backup set even if its tag does not match.
         -- In this case, the findValidBackupSet_c cursor did not do the
         -- tag checking for us, so we need to do it here.
         IF (tag = local.tag) THEN
            -- We've found a match for the tag, so we are done.  This
            -- backupset meets all of the validation criteria.  There may be
            -- another set of pieces with a different copy# or a different
            -- deviceType that also meet the criteria.  If the caller wants to
            -- find them, he will have to use the find/getValidBackupSet
            -- procedures to get the entire list, or call this routine
            -- again.
            deb(DEB_IN, 'tag matches');
            rc := SUCCESS;
            deb(DEB_IN, 'exiting loop with rc: SUCCESS');
            EXIT validationLoop;
         ELSE
            -- Even though the tag does not match, we want to remember
            -- about this set of pieces.  Keep looking for a match for our
            -- tag though.
            deb(DEB_IN, 'tag does not match, continuing search');
            rc := SUCCESS;
         END IF;
      ELSE
         -- Here, we know that the backupset is valid.  There may be multiple
         -- valid copies available, but we don't care.  The fact that one copy
         -- is available is good enough for us.
         rc := SUCCESS;
         deb(DEB_IN, 'exiting loop with rc: SUCCESS');
         EXIT validationLoop;
      END IF;
   END LOOP;
   IF (rc IS NULL) THEN
      deb(DEB_IN, 'rc is null, setting to unavailable');
      rc := dbms_rcvman.UNAVAILABLE;
   END IF;
   deb(DEB_EXIT, 'with rc:'||to_char(rc));
   RETURN rc;
END validateBackupSet0;
------------------------------ validateBackupSet ------------------------------
FUNCTION validateBackupSet(
   backupSetRec            IN     rcvRec_t
  ,tag                     IN     varchar2 DEFAULT NULL
  ,tagMatchRequired        IN     boolean  DEFAULT TRUE
  ,checkDeviceIsAllocated  IN     boolean  DEFAULT TRUE
  ,availableMask           IN     binary_integer
  ,validRec                OUT    validBackupSetRec_t)
RETURN binary_integer IS
   findTag      bp.tag%TYPE;
BEGIN
   deb(DEB_ENTER, 'validateBackupSet');
   IF (tagMatchRequired) THEN
      findTag := tag;
   ELSE
      -- Caller wants to know about backup sets even if they don't match
      -- the tag he is looking for, so don't do any tag filtering in the
      -- cursor.
      findTag := NULL;
   END IF;
  deb(DEB_IN, 'calling findValidBackupSet with:');
  deb(DEB_IN, ' tag=' || nvl(tag, 'NULL') ||
                    ' findTag=' || nvl(findTag, 'NULL') ||
                    ' tagMatchRequired=' || bool2char(tagMatchRequired) ||
                    ' checkDevice=' || bool2char(checkDeviceIsAllocated) ||
                    ' availableMask=' || to_char(availableMask));
   -- Open cursor
   findValidBackupSet(bsKey         => backupSetRec.bsKey_con,
                      pieceCount    => backupSetRec.pieceCount_con,
                      tag           => findTag,
                      availableMask => availableMask);
   deb(DEB_EXIT, 'with result from validateBackupSet0');
   RETURN validateBackupSet0(
      tag                    => tag,
      tagMatchRequired       => tagMatchRequired,
      checkDeviceIsAllocated => checkDeviceIsAllocated,
      validRec               => validRec);
END validateBackupSet;
------------------------------
-- Backup Piece Translation --
------------------------------
------------------------------- findBackupPiece -------------------------------
PROCEDURE findBackupPiece(
   bpKey        IN     number          DEFAULT NULL
  ,bsKey        IN     number          DEFAULT NULL
  ,tag          IN     varchar2        DEFAULT NULL
  ,handle       IN     varchar2        DEFAULT NULL
  ,deviceType   IN     varchar2        DEFAULT NULL
  ,copyNumber   IN     number          DEFAULT NULL
  ,statusMask   IN     binary_integer  DEFAULT BSavailable)
IS
BEGIN
   deb(DEB_ENTER, 'findBackupPiece');
   deb(DEB_IN, 'bpKey:'||nvl(bpKey, -1)||
          ' and bsKey:'||nvl(bsKey, -1));
   validateState(getBackupPieceCursor);
   IF (bpKey IS NOT NULL) THEN
      deb(DEB_OPEN, 'findBackupPieceBpKey');
      OPEN findBackupPieceBpKey(bpKey       => bpKey,
                                tag         => tag,
                                handle      => handle,
                                deviceType  => deviceType,
                                copyNumber  => copyNumber,
                                statusMask  => statusMask);
      getBackupPieceCursor := 'findBackupPieceBpKey';
   ELSIF (bsKey IS NOT NULL) THEN
      deb(DEB_OPEN, 'findBackupPieceBsKey');
      OPEN findBackupPieceBsKey(bsKey       => bsKey,
                                tag         => tag,
                                handle      => handle,
                                deviceType  => deviceType,
                                copyNumber  => copyNumber,
                                statusMask  => statusMask);
      getBackupPieceCursor := 'findBackupPieceBsKey';
   ELSE
      deb(DEB_OPEN, 'findBackupPiece_c');
      OPEN findBackupPiece_c(   tag         => tag,
                                handle      => handle,
                                deviceType  => deviceType,
                                copyNumber  => copyNumber,
                                statusMask  => statusMask);
      getBackupPieceCursor := 'findBackupPiece_c';
   END IF;
   -- Initialize all of the getBackupPiece variables to their default
   -- state.
   getBackupPieceNoRows.error     := NULL;
   getBackupPieceDuplicates       := TRUE#;
   getBackupPieceLast.pieceNumber := NULL;
   getBackupPieceDeviceType       := deviceType;
   getBackupPieceExpectedPieces   := NULL;
   getBackupPiecePieceCount       := 0;
   getBackupPieceByHandle         := FALSE;
   getBackupPieceAvailableMask    := NULL;
   deb(DEB_EXIT);
END findBackupPiece;
------------------------------------------
-- Compute Recovery Actions Subroutines --
------------------------------------------
--------------------------------- rcvRecPush ----------------------------------
PROCEDURE rcvRecPush(
   rcvRec IN rcvRec_t)
IS
BEGIN
   rcvRecStack.extend;
   rcvRecStack(rcvRecStack.last) := rcvRec;
END rcvRecPush;
---------------------------------- rcvRecGet ----------------------------------
PROCEDURE rcvRecGet(
   indx   IN  number
  ,rcvRec OUT rcvRec_t)
IS
BEGIN
   rcvRec := rcvRecStack(indx);
END rcvRecGet;
---------------------------------- rcvRecTop ----------------------------------
PROCEDURE rcvRecTop(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   IF (rcvRecStack.count = 0) THEN
      rcvRec := NULL;
   ELSE
      rcvRecGet(rcvRecStack.count, rcvRec);
   END IF;
END rcvRecTop;
---------------------------------- rcvRecPop ----------------------------------
PROCEDURE rcvRecPop(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   rcvRecTop(rcvRec);
   rcvRecStack.trim;
END rcvRecPop;
-------------------------------- rcvRecConvert --------------------------------
PROCEDURE rcvRecConvert(
   rcvRec IN OUT rcvRec_t)
IS
BEGIN
  -- Get rid of any nulls that would be unacceptable to the pre-8.1.6
  -- RMAN.  The pre-8.1.6 RMAN did not use null-indicators consistantly.
  rcvRec.recid_con      := nvl(rcvRec.recid_con, 0);
  rcvRec.stamp_con      := nvl(rcvRec.stamp_con, 0);
  rcvRec.setStamp_con   := nvl(rcvRec.setStamp_con, 0);
  rcvRec.setCount_con   := nvl(rcvRec.setCount_con, 0);
  rcvRec.fileName_con   := nvl(rcvRec.fileName_con, 'NULL');
  rcvRec.blockSize_con  := nvl(rcvRec.blockSize_con, 0);
  rcvRec.blocks_con     := nvl(rcvRec.blocks_con, 0);
  rcvRec.deviceType_con := nvl(rcvRec.deviceType_con, 'NULL');
END rcvRecConvert;
--------------------------------- printRcvRec ---------------------------------
PROCEDURE printRcvRec(
   action IN rcvRec_t)
IS
   l              varchar2(600);
   cfcretime      varchar2(100);
   action_deleted boolean;
BEGIN
   ------------------------
   -- Recovery Container --
   ------------------------
   deb(DEB_PRINT, 'DUMPING RECOVERY CONTAINER');
   -- Print the containter type
   IF (action.type_con = backupSet_con_t) THEN
      IF (action.type_act = full_act_t) THEN
         deb(DEB_PRINT, ' Full Backup Set');
      ELSE
         deb(DEB_PRINT, ' Incremental Backup Set');
      END IF;
   ELSIF (action.type_con = proxyCopy_con_t) THEN
      deb(DEB_PRINT, ' Proxy Backup');
   ELSIF (action.type_con = imageCopy_con_t) THEN
      deb(DEB_PRINT, ' Datafile Copy');
   ELSIF (action.type_con = offlineRangeRec_con_t) THEN
      IF (action.type_act = offlineRange_act_t) THEN
         deb(DEB_PRINT, ' Offline Range Record');
      ELSIF (action.type_act = cleanRange_act_t) THEN
         deb(DEB_PRINT, ' Clean Range');
      ELSIF (action.type_act = implicitRange_act_t) THEN
         deb(DEB_PRINT, ' Implicit Offline Range');
      ELSIF (action.type_act = spanningRange_act_t) THEN
         deb(DEB_PRINT, ' Spanning Offline Range');
      ELSE
         deb(DEB_PRINT, ' Unknown Offline Range Action Type');
      END IF;
   ELSE
      deb(DEB_PRINT, ' Uknown recovery container type');
   END IF;
   -- Print the type-specific containter data
   IF (action.type_con = backupSet_con_t) THEN
      deb(DEB_PRINT, '   bsKey=' || to_char(action.bsKey_con) ||
          '  bsRecid=' || to_char(action.bsRecid_con) ||
          '  bsStamp=' || to_char(action.bsStamp_con) ||
          '  setStamp=' || to_char(action.setStamp_con) ||
          '  setCount=' || to_char(action.setCount_con));
      deb(DEB_PRINT, '   bsLevel=' || to_char(action.bsLevel_con) ||
          '  bsType=' || action.bsType_con ||
          '  pieceCount=' || to_char(action.pieceCount_con));
   ELSIF (action.type_con = proxyCopy_con_t OR
          action.type_con = imageCopy_con_t) THEN
      deb(DEB_PRINT, '   fileName=' || action.fileName_con);
   END IF;
   -- Print the remaining container data
   l := ' ';
   -- key_con
   IF (action.key_con is not null) THEN
      l := l || '  key=' || to_char(action.key_con);
   END IF;
   -- recid_con, stamp_con
   IF (action.recid_con is not null) THEN
      l := l || '  recid=' || to_char(action.recid_con) ||
                '  stamp=' || to_char(action.stamp_con);
   END IF;
   -- status_con
   IF (action.status_con is not null) THEN
      l := l || '  status=' || action.status_con;
   END IF;
   IF (length(l) > 2) THEN
      deb(DEB_PRINT, l);
   END IF;
   l := ' ';
   -- tag
   IF (action.tag_con is not null) THEN
      l := l || '  tag=' || action.tag_con;
   END IF;
   -- compTime
   IF (action.compTime_con is not null) THEN
      l := l || '  compTime=' || to_char(action.compTime_con);
   END IF;
   IF (length(l) > 2) THEN
      deb(DEB_PRINT, l);
   END IF;
   l := ' ';
   IF (action.deviceType_con is not null) THEN
      l := l || '  deviceType=' || action.deviceType_con;
   END IF;
   IF (action.blocks_con is not null) THEN
      l := l || '  blocks=' || to_char(action.blocks_con) ||
           '  blockSize=' || to_char(action.blockSize_con);
   END IF;
   IF (action.cfCreationTime_con is not null) THEN
      l := l || '  cfCreationTime=' || to_char(action.cfCreationTime_con);
   END IF;
   IF (action.pieceNumber_con is not null) THEN
      l := l || '  pieceNumber=' || to_char(action.pieceNumber_con);
   END IF;
   IF (action.bpCompTime_con is not null) THEN
      l := l || '  bpCompTime=' || to_char(action.bpCompTime_con);
   END IF;
   IF (length(l) > 2) THEN
      deb(DEB_PRINT, l);
   END IF;
   l := ' ';
   ---------------------
   -- Recovery Action --
   ---------------------
   -- fromSCN
   IF (action.fromSCN_act is not null) THEN
      l := l || '  fromSCN=' || to_char(action.fromSCN_act);
   END IF;
   -- toSCN toTime
   IF (action.toSCN_act is not null) THEN
      l := l || '  toSCN=' || to_char(action.toSCN_act) ||
           '  toTime=' || to_char(action.toTime_act);
   END IF;
   -- level
   IF (action.level_act is not null) THEN
      l := l || '  level=' || to_char(action.level_act);
   END IF;
   IF (length(l) > 2) THEN
      deb(DEB_PRINT, l);
   END IF;
   l := ' ';
   IF (action.rlgSCN_act is not null) THEN
      l := l || '  rlgSCN=' || to_char(action.rlgSCN_act) ||
           '  rlgTime=' || to_char(action.rlgTime_act) ||
           '  dbincKey=' || to_char(action.dbincKey_act);
   END IF;
   IF (length(l) > 2) THEN
      deb(DEB_PRINT, l);
   END IF;
   l := ' ';
   IF (action.afzSCN_act is not null) THEN
      l := l || '  afzSCN=' || to_char(action.afzSCN_act);
   END IF;
   IF (length(l) > 2) THEN
      deb(DEB_PRINT, l);
   END IF;
   l := ' ';
   IF (action.rfzSCN_act is not null) THEN
      l := l || '  rfzSCN=' || to_char(action.rfzSCN_act) ||
           '  rfzTime=' || to_char(action.rfzTime_act);
   END IF;
   IF (length(l) > 2) THEN
      deb(l);
   END IF;
   l := ' ';
   ---------------------
   -- Recovery Object --
   ---------------------
   IF (action.dfNumber_obj IS NOT NULL) THEN
      l := l || '  dfNumber=' || to_char(action.dfNumber_obj) ||
                '  creationSCN=' || to_char(action.dfCreationSCN_obj);
      deb(DEB_PRINT, l);
      l := ' ';
      l := l || '  keep_options=' || nvl(to_char(action.keep_options), 'NULL') ||
                '  keep_until='   || nvl(to_char(action.keep_until), 'NULL');
      deb(DEB_PRINT, l);
      IF (action.cfSequence_obj IS NOT NULL) THEN
         l := ' ';
         l := l || '  cfSequence=' || to_char(action.cfSequence_obj) ||
                   '  cfDate=' || to_char(action.cfDate_obj);
         deb(DEB_PRINT, l);
      END IF;
   ELSIF (action.logSequence_obj IS NOT NULL) THEN
      l := l || '  logSequence=' || to_char(action.logSequence_obj);
      deb(DEB_PRINT, l);
      l := ' ';
      l := l || '  logThread=' || to_char(action.logThread_obj);
      deb(DEB_PRINT, l);
      l := ' ';
      l := l || '  logLowSCN=' || to_char(action.logLowSCN_obj);
      deb(DEB_PRINT, l);
      l := ' ';
      l := l || '  logLowTime=' || to_char(action.logLowTime_obj);
      deb(DEB_PRINT, l);
      l := ' ';
      l := l || '  logNextSCN=' || nvl(to_char(action.logNextSCN_obj), 'NULL');
      deb(DEB_PRINT, l);
      l := ' ';
      l := l || '  logNextTime=' || to_char(action.logNextTime_obj);
      deb(DEB_PRINT, l);
      l := ' ';
      l := l || '  logRlgSCN=' || to_char(action.logRlgSCN_obj);
      deb(DEB_PRINT, l);
      l := ' ';
      l := l || '  logRlgTime=' || to_char(action.logRlgTime_obj);
      deb(DEB_PRINT, l);
   ELSIF (action.toTime_act IS NOT NULL) THEN
      deb(DEB_PRINT, '  SPFILE');
      deb(DEB_PRINT, '  modification_time=' ||  to_char(action.toTime_act));
      l := ' ';
      l := l || '  keep_options=' || nvl(to_char(action.keep_options), 'NULL') ||
                '  keep_until='   || nvl(to_char(action.keep_until), 'NULL');
      deb(DEB_PRINT, l);
   ELSE
      deb(DEB_PRINT, '  Unknown Recovery Object');
   END IF;
EXCEPTION
   WHEN OTHERS THEN
   deb(DEB_PRINT, 'printRcvRec: caught an exception, aborting print');
   RETURN;
END printRcvRec;
-- See if redo is needed to fill a gap between this action and the one
-- that follows it, which is already on the rcvRecStack and is pointed to
-- by rcvRecStackState.lowAction
---------------------------------- redoNeeded ---------------------------------
FUNCTION redoNeeded(
   action IN rcvRec_t)
RETURN boolean IS
BEGIN
   deb(DEB_ENTER, 'redoNeeded');
   deb(DEB_PRINT, 'ENTERING redoNeeded');
   IF (rcvRecStackState.lowAction > 0 AND   -- Have a non-full_act_t on stack?
       action.toSCN_act <
       rcvRecStack(rcvRecStackState.lowAction).fromSCN_act) THEN
      deb(DEB_EXIT, 'with: TRUE');
      RETURN TRUE;
   ELSE
      deb(DEB_EXIT, 'with: FALSE');
      RETURN FALSE;
   END IF;
END redoNeeded;
---------------------------------- canAddRedo ---------------------------------
FUNCTION canAddRedo(
   isAncestor    IN boolean
  ,from_scn      IN number
  ,from_rlgscn   IN number
  ,to_action     IN rcvRec_t
  ,partial_rcv   IN boolean
  ,doingRecovery IN boolean)
RETURN number IS
BEGIN
   deb(DEB_ENTER, 'canAddRedo');
   IF (from_rlgscn = this_reset_scn) THEN
      IF (partial_rcv) THEN
         deb(DEB_EXIT, 'with: action_OK');
         RETURN action_OK;
      ELSE
         -- A partial media recovery can only be done if we have a
         -- current controlfile.  A partial recovery does not
         -- recover the controlfile.  This could be implemented,
         -- but it requires using an enqueue to ensure only
         -- 1 process tries to recover the confile.
         -- Since we aren't recovering the controlfile,
         -- the file header won't be handled properly when
         -- we hit controlfile redo.  That is why we are
         -- requiring a current controlfile.  Since we don't have
         -- one, we will have to do database recovery on this datafile.
         -- It is possible that we have a current controlfile here,
         -- but RMAN currently does not support partial media recovery.
         deb(DEB_EXIT, 'with: action_FAIL');
         RETURN action_FAIL;
      END IF;
   ELSE
      deb(DEB_IN, 'from_rlgscn=' || nvl(to_char(from_rlgscn), 'NULL') ||
          ' this_reset_scn=' || to_char(this_reset_scn));
      IF (isAncestor) THEN
         deb(DEB_IN, 'isAncestor is TRUE;');
         -- RMAN cannot yet apply redo from the non-current incarnation.
         -- Someday this will be implemented.  The idea is that RMAN will have
         -- the DB mount a backup controlfile from the incarnation containing
         -- the logs we need to apply, and then recovery should just work
         -- normally since the logs, controlfile, and datafile(s) will all be
         -- from the same incarnation.  We will be able to apply redo from a
         -- non-current incarnation only if isAncestor is TRUE.  We don't want
         -- to apply redo from an incarnation that we do not know with
         -- certainty is one of our ancestors.  Otherwise, we could be
         -- applying redo to reach the start of an offline range spanning
         -- resetlogs, which could certainly be the wrong thing to do.  An
         -- offline range should contain the reset SCN and timestamp of the
         -- incarnation in which the offline range started, but unfortunately
         -- it does not.
         -- Now, we just document the above procedure. So, the report/delete
         -- obsolete algorithm should not ignore previous incarnations.
         -- NOTE: REPORT/DELETE OBSOLETE sets allIncarnations to TRUE
         --       while LIST RECOVERABLE command does not.
         IF (doingRecovery) THEN
           deb(DEB_EXIT, 'with: action_OLD_REDO (doingRecovery)');
           RETURN action_OLD_REDO;
         ELSE
           IF (allIncarnations = TRUE# AND NOT doingRecovery) THEN
              deb(DEB_EXIT, 'with: action_OK (not doingRecovery)');
              RETURN action_OK;
           ELSE
             deb(DEB_EXIT, 'with: action_OLD_REDO (allIncarnations is FALSE)');
             RETURN action_OLD_REDO;
           END IF;
         END IF;
      ELSE
         deb(DEB_IN, 'isAncestor is FALSE;');
         -- We should never attempt to apply redo from an incartion that
         -- we don't know with certainty is one of our ancestors.
         deb(DEB_EXIT, 'with: action_OLD_REDO');
         RETURN action_OLD_REDO;
      END IF;
   END IF;
   deb(DEB_EXIT, 'with undefined status');
END canAddRedo;
----------------------------------- addRedo -----------------------------------
FUNCTION addRedo(
   isAncestor    IN boolean
  ,from_scn      IN number
  ,from_rlgscn   IN number
  ,to_action     IN rcvRec_t
  ,partial_rcv   IN boolean
  ,doingRecovery IN boolean)
RETURN number IS
   canAdd      number;
   redoRec     rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'addRedo');
   canAdd := canAddRedo(isAncestor, from_scn, from_rlgscn,
                        to_action, partial_rcv, doingRecovery);
   IF (canAdd = action_FAIL) THEN
      -- Trim to the last save point.  If we are doing RESTORE or RECOVER,
      -- then this will discard all actions we have stacked so far.
      -- If we are doing LIST, this will discard all actions up to
      -- the last full/level 0/copy/proxy-copy that we found.  We never
      -- need to trim actions that come after the save point since we
      -- know they can be applied.
      deb(DEB_IN, 'trimming to save_point');
      -- Since we have a gap in the redo stream here, reset lowAction
      -- to 0.  No actions that may be coming after this one will cover
      -- this gap since their to_scn's must be <= this action's.
      -- It is possible that the lowAction is about to be trimmed, but
      -- even if it remains on the stack, we have a broken chain and
      -- need to start a new one.
      rcvRecStackState.lowAction := 0;
      rcvRecStack.trim(rcvRecStack.last -
                       greatest(rcvRecStackState.savePoint,
                                rcvRecStackState.top));
      deb(DEB_EXIT, 'with: action_FAIL');
      RETURN action_FAIL;
   ELSIF (canAdd = action_OK) THEN
      redoRec.type_act          := redo_act_t;
      redoRec.fromSCN_act       := from_scn;
      redoRec.toSCN_act         := to_action.fromSCN_act;
      redoRec.toTime_act        := to_date(null);
      redoRec.rlgSCN_act        := from_rlgscn;
      rcvRecPush(redoRec);
      -- ### Some other fields should be filled in, but this code path never
      -- taken currently, so doesn't matter yet.
      deb(DEB_IN, 'from_scn=' || to_char(from_scn) ||
          ' to_scn=' || to_char(to_action.fromSCN_act));
      deb(DEB_EXIT, 'with: action_OK');
      RETURN action_OK;
   ELSE                                         -- ancestral incarnation
      -- Application of redo from an ancestral incarnation is not supported.
      -- However, we cannot trim these actions as we did in the case above
      -- because they are required to reach the offline-range that spans
      -- the resetlogs.  So we simply return an error.
      deb(DEB_EXIT, 'with: action_OLD_REDO');
      RETURN action_OLD_REDO;
   END IF;
   deb(DEB_EXIT, 'with undefined status');
END addRedo;
---------------------------------- addAction ----------------------------------
FUNCTION addAction(                             -- add to the rcvRecStack
   actionIN      IN     rcvRec_t                -- if a backup set, we fill
                                                -- in the tag and deviceType
  ,partial_rcv   IN     boolean
  ,isAncestor    IN     boolean
  ,cf_scn        IN     number  DEFAULT NULL
  ,cf_cretime    IN     date    DEFAULT NULL
  ,cf_offrrid    IN     number  DEFAULT NULL
  ,allCopies     IN     boolean DEFAULT FALSE
  ,doingRecovery IN     boolean DEFAULT TRUE)
RETURN number IS
   action               rcvRec_t;
   validate_rc          number;
   cf_count             number;
   addRedo_rc           number;
   tagMatchRequired     boolean;
   validationRec        validBackupSetRec_t;
   lowAction            rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'addAction');
   deb(DEB_IN, ' action.type_con='|| to_char(action.type_con));
   action := actionIN;                  -- copy to local variable
   -- See if we have a gap that must be filled by redo.  We must make this
   -- check first because we want to return OLD_REDO if that condition
   -- applies.  We process actions in descending to_scn order, so it is OK to
   -- add a redo action to the stack even if we cannot apply this action
   -- because it fails validation or we don't have the right device type
   -- allocated.  The next action we see would require at least this much
   -- redo.  Note that this means we may have 2 adjacent redo actions on the
   -- stack.  getRecoveryAction will merge them.
   IF (redoNeeded(action)) THEN
      -- We need to do a partial media recovery from this to_scn to
      -- get all the way to the lowActions's from_scn.
      -- N.B:
      -- A clean range always belongs to the current incarnation since it
      -- comes from the controlfile and the controlfile defines the current
      -- incarnation.  Therefore, if this action is a clean range then we
      -- must be searching the current incarnation.  It is not possible for
      -- the recoveryActionCursor to return a clean range when searching
      -- recursively, even if we didn't know our parent incarnation.  If
      -- the clean range does not span the resetlogs SCN, then its from_scn
      -- will be greater than the target_scn for any recursive search, and
      -- the cursor will filter out the clean range.  If the clean range
      -- does span the resetlogs SCN, then the clean range's from_scn
      -- becomes the target SCN for the recursive searches, and the cursor
      -- will also filter it out.  Therefore, we know that the lowAction
      -- must be from the current incarnation.  So we can simply add a redo
      -- action to fill the gap between the clean range and the lowAction.
      rcvRecGet(rcvRecStackState.lowAction, lowAction);
      addRedo_rc := addRedo(isAncestor,
                            action.toSCN_act, action.rlgSCN_act,
                            lowAction,
                            partial_rcv,
                            doingRecovery);
      IF (addRedo_rc = action_OLD_REDO) THEN
         -- We cannot apply this action because there is an offline range
         -- in the future of this action that we must apply, and it would
         -- require redo to reach the offline range.
         deb(DEB_EXIT, 'with addRedo_rc: '||to_char(addRedo_rc));
         RETURN addRedo_rc;
      ELSE
         -- The other possible return codes from addRedo are
         -- OK and FAIL.  In either case, we are allowed to add this
         -- action to the stack.  The FAIL case is when partial_rcv
         -- is false, so addRedo we just discards the actions previously
         -- stacked up to the save point, if any.
         NULL;
      END IF;
   ELSE                                 -- redo not needed
      -- If the lowAction is an offline range, then this action must
      -- have a to_scn <= the offline range start SCN.
      -- We don't actually need to check this though.  The cursor looks at
      -- only those actions with a to_scn <= the target_scn.
      NULL;
   END IF;
   -- If this is a backup set, validate that it is available and we have the
   -- right device type allocated to restore/list it, and also check that it
   -- is available on a set of pieces with the right tag if a restoreTag has
   -- been specified.
   IF (action.type_con = backupSet_con_t) THEN
      IF (computeRA_allRecords = TRUE# OR restoreTag IS NULL) THEN
         tagMatchRequired := FALSE;
      ELSE
         tagMatchRequired := TRUE;
      END IF;
      -- Validate this backup set.  This checks to see that a complete set of
      -- pieces are available on the same device type.  We also discover
      -- if the pieces are all available with the same tag, and if so, from
      -- the same copy#.  These values are then stuffed into the rcvRec.
      -- It is possible that a complete set of pieces is available on multiple
      -- device types if the backupset has been copied.  In this case, the
      -- other device types are ignored.  The ordering is simply the collating
      -- sequence order for the deviceType (alphabetic).  Since "DISK"
      -- comes before "SBT_TAPE", this has the effect of prefering backupsets
      -- on disk over those on tape, which is desired.  It would be a better
      -- implementation to have a preference column in the bp table, but
      -- that is not really needed until we have something other than
      -- SBT_TAPE and DISK.
      --
      -- If we are really performing a restore, then the underlying query
      -- (findValidBackupSet) will be run twice, once from here and then again
      -- later when RMAN obtains the backup pieces for this set.  This is
      -- unfortunate, but unavoidable.  This is the reason why the copy#
      -- tag and deviceType are stuffed into the rcvRec, so that the later
      -- call to get the pieces can use those values in the query, which may
      -- improve its performance.  Also note that if this backupset is used
      -- to restore multiple datafiles, then we validate it once for each
      -- datafile.  It may be a good idea to keep a list of backup set keys
      -- that have been validated to improve performance when many datafiles
      -- are being restored.
      --
      -- For RMAN commands such as LIST, the tag, deviceType, and copy#s will
      -- be ignored.  As of 8.1.6, those commands use the findValidBackupSet
      -- procedure directly to obtain complete information about the
      -- availablity of the backup set.
      validate_rc :=
         validateBackupSet(backupSetRec           => action,
                           tag                    => restoreTag,
                           tagMatchRequired       => tagMatchRequired,
                           checkDeviceIsAllocated => TRUE,
                           availableMask          => computeRA_availableMask,
                           validRec               => validationRec);
      IF (validate_rc = dbms_rcvman.UNAVAILABLE) THEN
         deb(DEB_EXIT, '(backup set is unavailable) with: action_FAIL');
         RETURN action_FAIL;
      ELSIF (validate_rc = dbms_rcvman.AVAILABLE) THEN
         -- We cannot restore/list this backup set because we don't have the
         -- right device type allocated.  We want to remember this fact
         -- so that we can give the user a meaningful error message.
         computeRA_available := TRUE;
         deb(DEB_EXIT, '(dont have required device type) with: action_FAIL');
         RETURN action_FAIL;
      ELSIF (validate_rc = SUCCESS) THEN
         -- IF computeRA_allRecords is true and restoreTag is not
         -- null, then we set tagMatchRequired to false, so it is possible
         -- that this backupset did not validate with the right tag.  Check
         -- that the tag in the validationRec matches the restoreTag.  If not,
         -- then leave the tag_con field in the action record null.  This will
         -- cause this action to be skipped when getRecoveryAction is called.
         IF (validationRec.tag = restoreTag OR
             restoreTag IS NULL) THEN
            action.tag_con := validationRec.tag;
         END IF;
         action.deviceType_con := validationRec.deviceType;
         action.copyNumber_con := validationRec.copyNumber;
      END IF;
   ELSIF (action.type_con = proxyCopy_con_t) THEN
      -- Check that we have the right deviceType allocated.
      IF (isDeviceTypeAllocated(action.deviceType_con) = FALSE#) THEN
         -- We cannot restore/list this backup set because we don't have the
         -- right device type allocated.  We want to remember this fact
         -- so that we can give the user a meaningful error message.
         computeRA_available := TRUE;
         deb(DEB_EXIT, '(dont have required device type for proxy)'||
             ' with: action_FAIL');
         RETURN action_FAIL;
      END IF;
   ELSIF (action.type_con = imageCopy_con_t) THEN
      -- Check that we have a disk device allocated.
      IF (not diskDevice) THEN
         -- We don't have a disk device allocated, so we cannot
         -- use a datafile copy.
         computeRA_available := TRUE;
         deb(DEB_EXIT, '(dont have required device type for proxy)'||
             ' with: action_FAIL');
         RETURN action_FAIL;
      END IF;
   ELSIF (action.type_con = offlineRangeRec_con_t AND
          action.type_act = offlineRange_act_t) THEN
      -- First see if this offline range is in the current controlfile.
      -- If so, we are cool.  If not, then check that there exists at least
      -- one controlfile copy that contains this offline range.
      -- Note that if a controlfile contains no kccor records, then
      -- the oldest recid will be zero.  Both krmk.pc and krbc.c obey
      -- this convention.
      IF (cf_cretime = action.cfCreationTime_con AND
          action.recid_con >= cf_offrrid AND
          cf_offrrid > 0 and            -- contains at least 1 record
          cf_scn >= action.toSCN_act) THEN
         NULL;                          -- range is in current cf, we're cool
      ELSE
         SELECT count(*)
           INTO cf_count
           FROM ccf
          WHERE ccf.create_time = action.cfCreationTime_con AND
                ccf.min_offr_recid <= action.recid_con AND
                ccf.ckp_scn >= action.toSCN_act AND
                ccf.min_offr_recid > 0; -- contains at least 1 record
         IF (cf_count = 0) THEN
           deb(DEB_EXIT, '(no controlfile copy with offline range)'||
                  ' with: action_FAIL');
           RETURN action_FAIL;
         END IF;
      END IF;
   END IF;
   <<addAnother>>
   rcvRecPush(action);                  -- add record for this action
   deb(DEB_IN, ' Added action:');
   printRcvRec(action);
   IF (allCopies AND action.type_con = backupSet_con_t) THEN
      -- Keep calling validateBackupSet0 until it fails to return SUCCESS.
      validate_rc :=
         validateBackupSet0(tag                    => restoreTag,
                            tagMatchRequired       => tagMatchRequired,
                            checkDeviceIsAllocated => TRUE,
                            validRec               => validationRec);
      IF (validate_rc <> SUCCESS) THEN
         GOTO done;
      END IF;
      IF (validationRec.tag = restoreTag OR
          restoreTag IS NULL) THEN
         action.tag_con := validationRec.tag;
      END IF;
      action.deviceType_con := validationRec.deviceType;
      action.copyNumber_con := validationRec.copyNumber;
      GOTO addAnother;
   END IF;
   <<done>>
   -- Update the lowAction pointer and the savePoint pointer if necessary.
   IF (action.type_act = full_act_t) THEN
      -- new full means new savePoint
      deb(DEB_IN, ' action.type_act is range/full => setting savePoint='||
           to_char(rcvRecStack.last));
      rcvRecStackState.savePoint := rcvRecStack.last;
   ELSIF (rcvRecStackState.lowAction = 0) THEN
      -- no curent lowAction, then set
      rcvRecStackState.lowAction := rcvRecStack.last;
   ELSIF (action.fromSCN_act <
          rcvRecStack(rcvRecStackState.lowAction).fromSCN_act) THEN
      rcvRecStackState.lowAction := rcvRecStack.last;   -- new lowAction
   END IF;
   deb(DEB_EXIT, 'with: action_OK');
   RETURN action_OK;
END addAction;
----------------------------- fetchRecoveryAction -----------------------------
FUNCTION fetchRecoveryAction(
   cv           IN     rcvRecCursor_t
  ,df_ckpscn    IN     number
  ,action       IN OUT rcvRec_t)
RETURN boolean IS
   top          rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'fetchRecoveryAction');
   <<retry>>
   FETCH cv
    INTO action;
   IF (cv%NOTFOUND) THEN
      action.type_con := NULL;
      action.type_act := NULL;
      deb(DEB_EXIT, 'with: FALSE');
      RETURN FALSE;
   END IF;
   IF (action.compTime_con IS NULL AND          -- was null in 8.0.2
       action.type_con = backupSet_con_t) THEN
      action.compTime_con := stamp2date(action.bsStamp_con);
   END IF;
   IF (computeRA_allRecords = TRUE#) THEN
      deb(DEB_EXIT, 'with: TRUE');
      RETURN TRUE;
   END IF;
   -- Discard this action if its fromSCN is not less than the most recently
   -- stacked actions's fromSCN.  Also check that the resetlogs SCNs are the
   -- same.  If they differ, then keep this action.  This is necessary to
   -- avoid discarding a spanning offline range here.  The real offline range
   -- and the spanning range(s) have the same fromSCN.
   IF (rcvRecStack.count > 0) THEN
      rcvRecTop(top);
      IF (not (action.fromSCN_act < top.fromSCN_act) AND
          action.rlgSCN_act = top.rlgSCN_act) THEN
         deb(DEB_IN, 'discarding this action:');
         printRcvRec(action);
         GOTO retry;
      END IF;
   END IF;
   deb(DEB_EXIT, 'with: TRUE');
   RETURN TRUE;
END fetchRecoveryAction;
--------------------------- openRecoveryActionCursor --------------------------
PROCEDURE openRecoveryActionCursor(
   rcvRecCursor  IN OUT rcvRecCursor_t
  ,dbincKey      IN     number
  ,fno           IN     number
  ,creSCN        IN     number
  ,dfCkpSCN      IN     number
  ,dbincRlgSCN   IN     number
  ,dbincRlgTime  IN     date
  ,offlSCN       IN     number
  ,onlSCN        IN     number
  ,onlTime       IN     date
  ,cleanSCN      IN     number
  ,clean2SCN     IN     number
  ,clean2Time    IN     date
  ,targetSCN     IN     number)
IS
BEGIN
   deb(DEB_ENTER, 'openRecoveryActionCursor');
   deb(DEB_IN, 'target scn is ' || nvl(to_char(targetSCN), 'NULL'));
   -- NOTES:
   --
   -- Procedure "setUntilTime" attempts to estimate the untilSCN by querying
   -- all the scn/timestamp pairs in the recovery catalog whose timestamp is
   -- strictly less than the until time.  The result is an estimated untilSCN
   -- that is very likely to be less than the actual incomplete recovery SCN
   -- when the RECOVER UNTIL TIME is done.  I.e. estimated untilSCN is
   -- conservative.  This calculation considers checkpoint SCN/timestamps for
   -- backup datafiles and datafile copies, as well as their absolute fuzzy
   -- SCNs/completion timestamps.  We treat the completion timestamp as a
   -- reasonable estimate of the absolute fuzzy time.
   -- Note that the absolute fuzzy SCN can be equal to the until SCN because
   -- it is higher than any SCN in the backup.  We also allow the checkpoint
   -- SCN and media recovery fuzzy SCN to be equal to the until SCN.
   deb(DEB_OPEN, 'rcvRecCursor');
   OPEN rcvRecCursor FOR                    -- open the cursor
   -- Offline Ranges
   SELECT offlineRangeRec_con_t                 type_con,
          offr_key                              key_con,
          offr_recid                            recid_con,
          offr_stamp                            stamp_con,
          to_number(null)                       setStamp_con,
          to_number(null)                       setCount_con,
          to_number(null)                       bsRecid_con,
          to_number(null)                       bsStamp_con,
          to_number(null)                       bsKey_con,
          to_number(null)                       bsLevel_con,
          to_char(null)                         bsType_con,
          to_number(null)                       elapseSecs_con,
          to_number(null)                       pieceCount_con,
          to_char(null)                         fileName_con,
          to_char(null)                         tag_con,
          to_number(null)                       copyNumber_con,
          to_char(null)                         status_con,
          to_number(null)                       blocks_con,
          to_number(null)                       blockSize_con,
          to_char(null)                         deviceType_con,
          to_date(null)                         compTime_con,
          cf_create_time                        cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          offlineRange_act_t                    type_act,
          offline_scn                           fromSCN_act,
          online_scn                            toSCN_act,
          online_time                           toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          dbinc_key                             dbincKey_act,
          to_number(null)                       level_act,
          openRecoveryActionCursor.fno          dfNumber_obj,
          openRecoveryActionCursor.creSCN       dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          to_number(null)                       keep_options,
          to_date(null)                         keep_until,
          to_number(null)                       afzSCN_act,
          to_date(null)                         rfzTime_act,
          to_number(null)                       rfzSCN_act
     FROM offr
    WHERE dbinc_key  = openRecoveryActionCursor.dbincKey
      AND file#      = openRecoveryActionCursor.fno
      AND create_scn = openRecoveryActionCursor.creSCN
      AND (openRecoveryActionCursor.dfCkpSCN is null OR
           openRecoveryActionCursor.dfCkpSCN <= offline_scn)
      AND (openRecoveryActionCursor.targetSCN is null OR
           online_scn <= openRecoveryActionCursor.targetSCN)
      AND (untilSCN is null OR online_scn < untilSCN)
                                        -- If online_scn = untilSCN, don't
                                        -- apply the offline range.  The
                                        -- dictionary txn that commits the
                                        -- online occurred at a higher scn,
                                        -- and recovery will probably stop
                                        -- before getting to commit redo.
      AND cf_create_time is not null    -- offr recs added before 8.0.3 useless
      AND offr_stamp <> 0               -- stamp = 0 -> from kccfe
   UNION ALL
   -- Datafile Copies
   SELECT imageCopy_con_t                       type_con,
          cdf_key                               key_con,
          cdf_recid                             recid_con,
          cdf_stamp                             stamp_con,
          to_number(null)                       setStamp_con,
          to_number(null)                       setCount_con,
          to_number(null)                       bsRecid_con,
          to_number(null)                       bsStamp_con,
          to_number(null)                       bsKey_con,
          to_number(null)                       bsLevel_con,
          to_char(null)                         bsType_con,
          to_number(null)                       elapseSecs_con,
          to_number(null)                       pieceCount_con,
          fname                                 fileName_con,
          tag                                   tag_con,
          to_number(null)                       copyNumber_con,
          status                                status_con,
          blocks                                blocks_con,
          block_size                            blockSize_con,
          'DISK'                                deviceType_con,
          completion_time                       compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          full_act_t                            type_act,
          0                                     fromSCN_act,
          ckp_scn                               toSCN_act,
          ckp_time                              toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          dbinc_key                             dbincKey_act,
          to_number(null)                       level_act,
          openRecoveryActionCursor.fno          dfNumber_obj,
          openRecoveryActionCursor.creSCN       dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          keep_options                          keep_options,
          keep_until                            keep_until,
          abs_fuzzy_scn                         afzSCN_act,
          rcv_fuzzy_time                        rfzTime_act,
          rcv_fuzzy_scn                         rfzSCN_act
     FROM cdf
    WHERE dbinc_key  = openRecoveryActionCursor.dbincKey
      AND file#      = openRecoveryActionCursor.fno
      AND create_scn = openRecoveryActionCursor.crescn
      AND (openRecoveryActionCursor.dfCkpSCN is null OR
           openRecoveryActionCursor.dfCkpSCN < ckp_scn)
      AND (openRecoveryActionCursor.targetSCN is null OR
           ckp_scn <= openRecoveryActionCursor.targetSCN)
      AND (untilSCN is null OR
           greatest(ckp_scn, abs_fuzzy_scn, rcv_fuzzy_scn) <= untilSCN)
      AND status = 'A'
      AND (restoreTag is NULL OR
           tag = restoreTag OR
           computeRA_allRecords = TRUE#)
      AND (restoreSource is NULL OR restoreSource = COPY)
   UNION ALL
   -- Controlfile Copies
   SELECT imageCopy_con_t                       type_con,
          ccf_key                               key_con,
          ccf_recid                             recid_con,
          ccf_stamp                             stamp_con,
          to_number(null)                       setStamp_con,
          to_number(null)                       setCount_con,
          to_number(null)                       bsRecid_con,
          to_number(null)                       bsStamp_con,
          to_number(null)                       bsKey_con,
          to_number(null)                       bsLevel_con,
          to_char(null)                         bsType_con,
          to_number(null)                       elapseSecs_con,
          to_number(null)                       pieceCount_con,
          fname                                 fileName_con,
          tag                                   tag_con,
          to_number(null)                       copyNumber_con,
          status                                status_con,
          to_number(null)                       blocks_con,
          block_size                            blockSize_con,
          'DISK'                                deviceType_con,
          completion_time                       compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          full_act_t                            type_act,
          0                                     fromSCN_act,
          ckp_scn                               toSCN_act,
          ckp_time                              toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          dbinc_key                             dbincKey_act,
          to_number(null)                       level_act,
          openRecoveryActionCursor.fno          dfNumber_obj,
          openRecoveryActionCursor.creSCN       dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          keep_options                          keep_options,
          keep_until                            keep_until,
          to_number(null)                       afzSCN_act,
          to_date(null)                         rfzTime_act,
          to_number(null)                       rfzSCN_act
     FROM ccf
    WHERE dbinc_key  = openRecoveryActionCursor.dbincKey
      AND 0          = openRecoveryActionCursor.fno
      AND 0          = openRecoveryActionCursor.crescn
      AND (openRecoveryActionCursor.dfCkpSCN is null OR
           openRecoveryActionCursor.dfCkpSCN < ckp_scn)
      AND (openRecoveryActionCursor.targetSCN is null OR
           ckp_scn <= openRecoveryActionCursor.targetSCN)
      AND (untilSCN is null OR
           ckp_scn <= untilSCN)
      AND status = 'A'
      AND (restoreTag is NULL OR
           tag = restoreTag OR
           computeRA_allRecords = TRUE#)
      AND (restoreSource is NULL OR restoreSource = COPY)
   UNION ALL
   -- Backup Sets
   SELECT backupSet_con_t                       type_con,
          bdf.bdf_key                           key_con,
          bdf.bdf_recid                         recid_con,
          bdf.bdf_stamp                         stamp_con,
          bs.set_stamp                          setStamp_con,
          bs.set_count                          setCount_con,
          bs.bs_recid                           bsRecid_con,
          bs.bs_stamp                           bsStamp_con,
          bs.bs_key                             bsKey_con,
          bs.incr_level                         bsLevel_con,
          bs.bck_type                           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                                elapseSecs_con,
          bs.pieces                             pieceCount_con,
          to_char(null)                         fileName_con,
          to_char(null)                         tag_con,
          to_number(null)                       copyNumber_con,
          to_char(null)                         status_con,
          bdf.blocks                            blocks_con,
          bdf.block_size                        blockSize_con,
          to_char(null)                         deviceType_con,
          bdf.completion_time                   compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          decode(bdf.incr_scn,
                 0, full_act_t,
                 incremental_act_t)             type_act,
          bdf.incr_scn                          fromSCN_act,
          bdf.ckp_scn                           toSCN_act,
          bdf.ckp_time                          toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          dbinc.dbinc_key                       dbincKey_act,
          bdf.incr_level                        level_act,
          openRecoveryActionCursor.fno          dfNumber_obj,
          openRecoveryActionCursor.crescn       dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          bs.keep_options                       keep_options,
          bs.keep_until                         keep_until,
          bdf.abs_fuzzy_scn                     afzSCN_act,
          to_date(null)                         rfzTime_act,
          to_number(null)                       rfzSCN_act
     FROM bdf, bs, dbinc
    WHERE bdf.dbinc_key    = openRecoveryActionCursor.dbincKey
      AND bdf.file#        = openRecoveryActionCursor.fno
      AND bdf.create_scn   = openRecoveryActionCursor.crescn
      AND (openRecoveryActionCursor.dfCkpSCN IS NULL OR
           openRecoveryActionCursor.dfCkpSCN < bdf.ckp_scn)
      AND (openRecoveryActionCursor.targetSCN IS NULL OR
           bdf.ckp_scn <= openRecoveryActionCursor.targetscn)
      AND (untilSCN IS NULL OR
           greatest(bdf.ckp_scn, bdf.abs_fuzzy_scn) <= untilSCN)
      AND (restoreSource IS NULL OR restoreSource = BACKUP)
      AND dbinc.dbinc_key  = bdf.dbinc_key   -- join dbinc, bdf
      AND bs.bs_key        = bdf.bs_key      -- join bs, bdf
      AND bs.status = 'A'
   UNION ALL
   -- Backup Sets with controlfiles
   SELECT backupSet_con_t                       type_con,
          bcf.bcf_key                           key_con,
          bcf.bcf_recid                         recid_con,
          bcf.bcf_stamp                         stamp_con,
          bs.set_stamp                          setStamp_con,
          bs.set_count                          setCount_con,
          bs.bs_recid                           bsRecid_con,
          bs.bs_stamp                           bsStamp_con,
          bs.bs_key                             bsKey_con,
          0                                     bsLevel_con,
          bs.bck_type                           bsType_con,
          ((bs.completion_time - bs.start_time) * 86400)
                                                elapseSecs_con,
          bs.pieces                             pieceCount_con,
          to_char(null)                         fileName_con,
          to_char(null)                         tag_con,
          to_number(null)                       copyNumber_con,
          to_char(null)                         status_con,
          to_number(null)                       blocks_con,
          bcf.block_size                        blockSize_con,
          to_char(null)                         deviceType_con,
          bs.completion_time                    compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          full_act_t                            type_act,
          0                                     fromSCN_act,
          bcf.ckp_scn                           toSCN_act,
          bcf.ckp_time                          toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          dbinc.dbinc_key                       dbincKey_act,
          to_number(null)                       level_act,
          openRecoveryActionCursor.fno          dfNumber_obj,
          openRecoveryActionCursor.crescn       dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          bs.keep_options                       keep_options,
          bs.keep_until                         keep_until,
          to_number(null)                       afzSCN_act,
          to_date(null)                         rfzTime_act,
          to_number(null)                       rfzSCN_act
     FROM bcf, bs, dbinc
    WHERE bcf.dbinc_key    = openRecoveryActionCursor.dbincKey
      AND 0                = openRecoveryActionCursor.fno
      AND 0                = openRecoveryActionCursor.crescn
      AND (openRecoveryActionCursor.dfCkpSCN IS NULL OR
           openRecoveryActionCursor.dfCkpSCN < bcf.ckp_scn)
      AND (openRecoveryActionCursor.targetSCN IS NULL OR
           bcf.ckp_scn <= openRecoveryActionCursor.targetscn)
      AND (untilSCN IS NULL OR
           bcf.ckp_scn <= untilSCN)
      AND (restoreSource IS NULL OR restoreSource = BACKUP)
      AND dbinc.dbinc_key  = bcf.dbinc_key    -- join dbinc, bcf
      AND bs.bs_key        = bcf.bs_key       -- join bs, bcf
      AND bs.status = 'A'
   UNION ALL
   -- Proxy Datafile Backups
   SELECT proxyCopy_con_t                       type_con,
          xdf_key                               key_con,
          xdf_recid                             recid_con,
          xdf_stamp                             stamp_con,
          to_number(null)                       setStamp_con,
          to_number(null)                       setCount_con,
          to_number(null)                       bsRecid_con,
          to_number(null)                       bsStamp_con,
          to_number(null)                       bsKey_con,
          to_number(null)                       bsLevel_con,
          to_char(null)                         bsType_con,
          to_number(null)                       elapseSecs_con,
          to_number(null)                       pieceCount_con,
          handle                                fileName_con,
          tag                                   tag_con,
          to_number(null)                       copyNumber_con,
          status                                status_con,
          blocks                                blocks_con,
          block_size                            blockSize_con,
          device_type                           deviceType_con,
          completion_time                       compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          full_act_t                            type_act,
          0                                     fromSCN_act,
          ckp_scn                               toSCN_act,
          ckp_time                              toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          dbinc_key                             dbincKey_act,
          to_number(null)                       level_act,
          openRecoveryActionCursor.fno          dfNumber_obj,
          openRecoveryActionCursor.crescn       dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          keep_options                          keep_options,
          keep_until                            keep_until,
          abs_fuzzy_scn                         afzSCN_act,
          rcv_fuzzy_time                        rfzTime_act,
          rcv_fuzzy_scn                         rfzSCN_act
     FROM xdf
    WHERE dbinc_key  = openRecoveryActionCursor.dbincKey
      AND file#      = openRecoveryActionCursor.fno
      AND create_scn = openRecoveryActionCursor.crescn
      AND (openRecoveryActionCursor.dfCkpSCN IS NULL OR
           openRecoveryActionCursor.dfCkpSCN < ckp_scn)
      AND (openRecoveryActionCursor.targetSCN IS NULL OR
           ckp_scn <= openRecoveryActionCursor.targetscn)
      AND (untilSCN IS NULL OR
           greatest(ckp_scn, abs_fuzzy_scn, rcv_fuzzy_scn) <= untilSCN)
      AND status = 'A'
      AND (restoreTag is NULL OR
           tag = restoreTag OR
           computeRA_allRecords = TRUE#)
      AND (restoreSource is NULL OR restoreSource = BACKUP)
   UNION ALL
   -- Proxy Controlfile Backups
   SELECT proxyCopy_con_t                       type_con,
          xcf_key                               key_con,
          xcf_recid                             recid_con,
          xcf_stamp                             stamp_con,
          to_number(null)                       setStamp_con,
          to_number(null)                       setCount_con,
          to_number(null)                       bsRecid_con,
          to_number(null)                       bsStamp_con,
          to_number(null)                       bsKey_con,
          to_number(null)                       bsLevel_con,
          to_char(null)                         bsType_con,
          to_number(null)                       elapseSecs_con,
          to_number(null)                       pieceCount_con,
          handle                                fileName_con,
          tag                                   tag_con,
          to_number(null)                       copyNumber_con,
          status                                status_con,
          to_number(null)                       blocks_con,
          block_size                            blockSize_con,
          device_type                           deviceType_con,
          completion_time                       compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          full_act_t                            type_act,
          0                                     fromSCN_act,
          ckp_scn                               toSCN_act,
          ckp_time                              toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          dbinc_key                             dbincKey_act,
          to_number(null)                       level_act,
          openRecoveryActionCursor.fno          dfNumber_obj,
          openRecoveryActionCursor.crescn       dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          keep_options                          keep_options,
          keep_until                            keep_until,
          to_number(null)                       afzSCN_act,
          to_date(null)                         rfzTime_act,
          to_number(null)                       rfzSCN_act
     FROM xcf
    WHERE dbinc_key  = openRecoveryActionCursor.dbincKey
      AND 0          = openRecoveryActionCursor.fno
      AND 0          = openRecoveryActionCursor.crescn
      AND (openRecoveryActionCursor.dfCkpSCN IS NULL OR
           openRecoveryActionCursor.dfCkpSCN < ckp_scn)
      AND (openRecoveryActionCursor.targetSCN IS NULL OR
           ckp_scn <= openRecoveryActionCursor.targetscn)
      AND (untilSCN IS NULL OR
           ckp_scn <= untilSCN)
      AND status = 'A'
      AND (restoreTag is NULL OR
           tag = restoreTag OR
           computeRA_allRecords = TRUE#)
      AND (restoreSource is NULL OR restoreSource = BACKUP)
   UNION ALL
   -- Implicit offline Ranges
   SELECT offlineRangeRec_con_t                 type_con,
          to_number(null)                       key_con,
          to_number(null)                       recid_con,
          to_number(null)                       stamp_con,
          to_number(null)                       setStamp_con,
          to_number(null)                       setCount_con,
          to_number(null)                       bsRecid_con,
          to_number(null)                       bsStamp_con,
          to_number(null)                       bsKey_con,
          to_number(null)                       bsLevel_con,
          to_char(null)                         bsType_con,
          to_number(null)                       elapseSecs_con,
          to_number(null)                       pieceCount_con,
          to_char(null)                         fileName_con,
          to_char(null)                         tag_con,
          to_number(null)                       copyNumber_con,
          to_char(null)                         status_con,
          to_number(null)                       blocks_con,
          to_number(null)                       blockSize_con,
          to_char(null)                         deviceType_con,
          to_date(null)                         compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          implicitRange_act_t                   type_act,
          openRecoveryActionCursor.offlSCN      fromSCN_act,
          openRecoveryActionCursor.onlSCN       toSCN_act,
          openRecoveryActionCursor.onlTime      toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          openRecoveryActionCursor.dbincKey     dbincKey_act,
          to_number(null)                       level_act,
          fno                                   dfNumber_obj,
          crescn                                dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          to_number(null)                       keep_options,
          to_date(null)                         keep_until,
          to_number(null)                       afzSCN_act,
          to_date(null)                         rfzTime_act,
          to_number(null)                       rfzSCN_act
     FROM dual
    WHERE offlscn <> 0
      AND (openRecoveryActionCursor.dfCkpSCN is null OR
           openRecoveryActionCursor.dfCkpSCN <=
           openRecoveryActionCursor.offlSCN)
      AND (openRecoveryActionCursor.onlSCN >=   -- belongs to this incarnation
           openRecoveryActionCursor.dbincRlgSCN)
      AND (openRecoveryActionCursor.targetSCN is null OR
           openRecoveryActionCursor.onlscn <=   -- don't advance ckpt beyond
           openRecoveryActionCursor.targetSCN)  -- targetSCN
      AND (untilSCN is null OR        -- don't advance ckpt beyond until scn
           openRecoveryActionCursor.onlSCN < untilSCN)
   UNION ALL
   SELECT offlineRangeRec_con_t                 type_con,
          to_number(null)                       key_con,
          to_number(null)                       recid_con,
          to_number(null)                       stamp_con,
          to_number(null)                       setStamp_con,
          to_number(null)                       setCount_con,
          to_number(null)                       bsRecid_con,
          to_number(null)                       bsStamp_con,
          to_number(null)                       bsKey_con,
          to_number(null)                       bsLevel_con,
          to_char(null)                         bsType_con,
          to_number(null)                       elapseSecs_con,
          to_number(null)                       pieceCount_con,
          to_char(null)                         fileName_con,
          to_char(null)                         tag_con,
          to_number(null)                       copyNumber_con,
          to_char(null)                         status_con,
          to_number(null)                       blocks_con,
          to_number(null)                       blockSize_con,
          to_char(null)                         deviceType_con,
          to_date(null)                         compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          cleanRange_act_t                      type_act,
          openRecoveryActionCursor.cleanSCN     fromSCN_act,
          openRecoveryActionCursor.clean2SCN    toSCN_act,
          openRecoveryActionCursor.clean2Time   toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          openRecoveryActionCursor.dbincKey     dbincKey_act,
          to_number(null)                       level_act,
          fno                                   dfNumber_obj,
          crescn                                dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          to_number(null)                       keep_options,
          to_date(null)                         keep_until,
          to_number(null)                       afzSCN_act,
          to_date(null)                         rfzTime_act,
          to_number(null)                       rfzSCN_act
     FROM dual
    WHERE openRecoveryActionCursor.cleanscn <> 0
      AND (openRecoveryActionCursor.dfCkpSCN is null OR
           openRecoveryActionCursor.dfCkpSCN <=
           openRecoveryActionCursor.cleanscn)
      AND -- belongs to this incarnation
          (openRecoveryActionCursor.clean2scn >=
           openRecoveryActionCursor.dbincRlgSCN)
      AND -- ignore if starts beyond target
          (openRecoveryActionCursor.targetscn is null OR
           openRecoveryActionCursor.cleanscn <
           openRecoveryActionCursor.targetSCN)
      AND -- If clean2scn is infinite, then we processed this when scanning
          -- the current incarnation,
          (openRecoveryActionCursor.targetSCN is null OR
           openRecoveryActionCursor.clean2SCN <=
           openRecoveryActionCursor.targetSCN)
      AND -- don't advance ckpt beyond until scn, unless we don't know
          -- where this offline range ends.
          (untilscn is null OR
           openRecoveryActionCursor.clean2SCN <= untilSCN OR
           openRecoveryActionCursor.clean2SCN = 281474976710655)
   UNION ALL
   SELECT offlineRangeRec_con_t                 type_con,
          to_number(null)                       key_con,
          to_number(null)                       recid_con,
          to_number(null)                       stamp_con,
          to_number(null)                       setStamp_con,
          to_number(null)                       setCount_con,
          to_number(null)                       bsRecid_con,
          to_number(null)                       bsStamp_con,
          to_number(null)                       bsKey_con,
          to_number(null)                       bsLevel_con,
          to_char(null)                         bsType_con,
          to_number(null)                       elapseSecs_con,
          to_number(null)                       pieceCount_con,
          to_char(null)                         fileName_con,
          to_char(null)                         tag_con,
          to_number(null)                       copyNumber_con,
          to_char(null)                         status_con,
          to_number(null)                       blocks_con,
          to_number(null)                       blockSize_con,
          to_char(null)                         deviceType_con,
          to_date(null)                         compTime_con,
          to_date(null)                         cfCreationTime_con,
          to_number(null)                       pieceNumber_con,
          to_date(null)                         bpCompTime_con,
          spanningRange_act_t                   type_act,
          openRecoveryActionCursor.targetSCN    fromSCN_act,
          to_number(null)                       toSCN_act,
          to_date(null)                         toTime_act,
          openRecoveryActionCursor.dbincRlgSCN  rlgSCN_act,
          openRecoveryActionCursor.dbincRlgTime rlgTime_act,
          openRecoveryActionCursor.dbincKey     dbincKey_act,
          to_number(null)                       level_act,
          fno                                   dfNumber_obj,
          crescn                                dfCreationSCN_obj,
          to_number(null)                       cfSequence_obj,
          to_date(null)                         cfDate_obj,
          to_number(null)                       logSequence_obj,
          to_number(null)                       logThread_obj,
          to_number(null)                       logRlgSCN_obj,
          to_date(null)                         logRlgTime_obj,
          to_number(null)                       logLowSCN_obj,
          to_date(null)                         logLowTime_obj,
          to_number(null)                       logNextSCN_obj,
          to_date(null)                         logNextTime_obj,
          to_number(null)                       keep_options,
          to_date(null)                         keep_until,
          to_number(null)                       afzSCN_act,
          to_date(null)                         rfzTime_act,
          to_number(null)                       rfzSCN_act
     FROM dual
    WHERE -- a offline range which spans multiple resetlogs triggers
          -- this condition
          openRecoveryActionCursor.targetSCN <
          openRecoveryActionCursor.dbincRlgSCN
    ORDER BY 27 desc, -- toSCN_act
             26  asc, -- fromSCN_act
             1   asc, -- type_con
             4  desc; -- stamp_con
   deb(DEB_EXIT);
END openRecoveryActionCursor;
---------------------------- computeRecoveryActions ---------------------------
FUNCTION computeRecoveryActions(
   fno         IN number        -- Datafile number.
  ,crescn      IN number        -- Datafile creation SCN.
  ,df_rlgscn   IN number        -- Datafile resetlogs SCN.
                                -- Null if this is a RESTORE or LIST, else this
                                -- is the value in the datafile header for the
                                -- datafile we are RECOVERing.
  ,df_rlgtime  IN date          -- Datafile resetlogs time.
                                -- Null if df_rlgscn is null, else value from
                                -- datafile header.
  ,df_ckpscn   IN number        -- Datafile checkpoint SCN.
                                -- Null if df_rlgscn is null, else value from
                                -- datafile header.
  ,offlscn     IN number        -- kccfeofs (may be 0).
  ,onlscn      IN number        -- kccfeonc (0 if offlscn is 0).
  ,onltime     IN date          -- kccfeonc_time (ignored if kccfeofs is 0)
  ,cleanscn    IN number        -- kccfecps if either SOR or WCC set, else 0.
  ,clean2scn   IN number        -- CF ckpt SCN if WCC set.
                                -- Infinity if SOR bit set, else 0.
  ,clean2time  IN date          -- cf_checkpoint_time if WCC,
                                -- SYSDATE if SOR bit set.
  ,allowfuzzy  IN boolean       -- TRUE if can be fuzzy at until SCN/time,
                                -- FALSE if not.
  ,partial_rcv IN boolean
  ,target_scn  IN number        -- This is the SCN to which we want to recover
                                -- the datafile.  Null unless we call
                                -- ourselves recursively to search a prior
                                -- incarnation.  We search prior incarnations
                                -- only when there is an offline range
                                -- spanning the resetlogs SCN.  So this SCN is
                                -- really the offline range start SCN.
  ,dbinc_key   IN number        -- The key of the database incarnation to
                                -- search in.  This may be different from
                                -- df_rlgscn, and it may be different from the
                                -- package var "this_dbinc_key".
  ,cf_scn      IN number
  ,cf_cretime  IN date          -- controlfile creation time.
                                -- NULL if none mounted.
  ,cf_offrrid  IN number        -- recid of oldest offline range in controlfile
                                -- NULL if none mounted.
  ,test_search IN boolean       -- if TRUE, then we have called ourself
                                --  recursively and are not sure this is an
                                -- ancestral incarnation
  ,done        IN OUT boolean   -- set to TRUE if successful.  (IN mode so
                                -- we can test it).
  ,allCopies   IN boolean)      -- if true, then stack all copies of
                                -- a backup set if it was duplexed or copied.
-- NOTES:
-- If all copies is FALSE, then we should at least count the number of copies
-- of a backup set in addAction and save this number in the rcvRec.  This
-- would tell us how many copies of a backupset there are, which would be
-- useful for RMAN to know.  For example, if the customer wanted redundancy=2
-- but there was only 1 copy of an incremental backup, then this incremental
-- could not be considered as a substitute for archivelogs.
RETURN boolean IS
   ---------------------
   -- LOCAL VARIABLES --
   ---------------------
   r_act_cv             rcvRecCursor_t; -- cursor variable
   action               rcvRec_t;       -- current row
   lastAction           rcvRec_t;
   parentDbincKey       number;         -- my parent dbinc's key
   dbinc_rlgscn         number;         -- resetlogs scn for dbinc_key
   dbinc_rlgtime        date;           -- resetlogs time for dbinc_key
   CURSOR dbinc_cursor(db_key number, rstscn number) IS
   SELECT dbinc_key
     FROM dbinc
    WHERE dbinc.db_key = dbinc_cursor.db_key
      AND dbinc.reset_scn < dbinc_cursor.rstscn;
   dbinc_row            dbinc_cursor%ROWTYPE;
   savedrcvRecStackState rcvRecStackState_t;
   addAction_rc         number;         -- return code
   canAddRedo_rc        number;         -- return code
   addRedo_rc           number;         -- return code
   isAncestor           boolean;        -- TRUE if we find an action we could
                                        -- apply with to_scn = target_scn
   rc                   boolean;        -- return code from recursive search
                                        -- of possible parent incarnation
   done_flag            boolean;        -- for use in recursive calls
   doingRecovery        boolean;        -- doing RECOVER or not
BEGIN
   deb(DEB_ENTER, 'computeRecoveryActions');
   done := FALSE;
   IF (df_rlgscn is not null) THEN                      -- doing RECOVER
      doingRecovery := TRUE;
      deb(DEB_IN, ' Doing recovery.');
   ELSE
      doingRecovery := FALSE;
      deb(DEB_IN, ' Not doing recovery.');
   END IF;
   -- Compute this dbinc's resetlogs SCN and time --
   SELECT reset_scn, reset_time
     INTO dbinc_rlgscn, dbinc_rlgtime
     FROM dbinc
    WHERE dbinc.dbinc_key = computeRecoveryActions.dbinc_key;
   IF (doingRecovery) THEN                               -- doing RECOVER
      -- Check that this incarnation is reasonable for the
      -- datafile we are trying to recover.  We only want to look at
      -- incarnations with a resetlogs SCN >= the datafile's resetlogs SCN.
      IF (dbinc_rlgscn < df_rlgscn) THEN
         deb(DEB_PRINT, 'dbinc_rlgscn < df_rlgscn (' || to_char(dbinc_rlgscn) ||
             ' < ' || to_char(df_rlgscn) || ')');
         deb(DEB_EXIT, 'with: FALSE');
         RETURN FALSE;
      ELSIF (dbinc_rlgscn = df_rlgscn AND dbinc_rlgtime <> df_rlgtime) THEN
         deb(DEB_PRINT, 'dbinc_rlgtime <> df_rlgtime');
         deb(DEB_EXIT, 'with: FALSE');
         RETURN FALSE;
      END IF;
   END IF;
   IF (not test_search) THEN
      -- This is not test search of a prior incarnation, therefore
      -- we can set this flag right away.
      deb(DEB_IN, ' This is ancestor.');
      isAncestor := TRUE;
   ELSE
      isAncestor := FALSE;
   END IF;
   openRecoveryActionCursor(r_act_cv, dbinc_key,
                            fno, crescn, df_ckpscn,
                            dbinc_rlgscn, dbinc_rlgtime,
                            offlscn, onlscn, onltime,
                            cleanscn, clean2scn, clean2time, target_scn);
   ------------------------------------
   -- Process the rows from r_act_cv --
   ------------------------------------
<<action_loop>>
   LOOP
      <<next_row>>
      IF (fetchRecoveryAction(r_act_cv, df_ckpscn, action)) THEN
         -----------------------------
         -- Compute isAncestor flag --
         -----------------------------
         IF (bitand(action.type_con, backupMask_con_t) > 0 AND
             action.toSCN_act = target_scn) THEN
            deb(DEB_IN, ' This is ancestor.');
            isAncestor := TRUE;
         END IF;
         IF (action.type_con = offlineRangeRec_con_t) THEN
            -------------------
            -- OFFLINE RANGE --
            -------------------
            deb(DEB_IN, ' found an offline range' ||
                ' from=' || to_char(action.fromSCN_act) ||
                ' to=' || to_char(action.toSCN_act));
            IF (action.type_act = spanningRange_act_t) THEN
               ----------------------------------------------
               -- OFFLINE RANGE spanning multiple resetlogs -
               ----------------------------------------------
               deb(DEB_IN, ' offline range started before this resetlogs SCN');
               -- We don't need to add this action to the stack.  Just set
               -- addAction_rc to action_OK so that we will take the
               -- right path below and search our parent incarnation.
               addAction_rc := action_OK;
            ELSE
               addAction_rc := addAction(actionIN      => action,
                                         partial_rcv   => partial_rcv,
                                         isAncestor    => isAncestor,
                                         cf_scn        => cf_scn,
                                         cf_cretime    => cf_cretime,
                                         cf_offrrid    => cf_offrrid,
                                         doingRecovery => doingRecovery);
            END IF;
         ELSIF (action.type_con = backupSet_con_t AND
                action.type_act = incremental_act_t) THEN
            ----------------------------
            -- INCREMENTAL BACKUP SET --
            ----------------------------
            deb(DEB_IN, 'found an incremental backup set');
            addAction_rc := addAction(actionIN      => action,
                                      partial_rcv   => partial_rcv,
                                      isAncestor    => isAncestor,
                                      allCopies     => allCopies,
                                      doingRecovery => doingRecovery);
         ELSIF (action.type_act = full_act_t) THEN
            ------------------------------------------------------------
            -- DATAFILE COPY or FULL or LEVEL 0 BACKUP SET/PROXY COPY --
            ------------------------------------------------------------
            deb(DEB_IN, 'found a copy/full/level0/proxy copy');
            IF (doingRecovery) THEN                  -- if doing a RECOVER
               -- Datafilecopies and full backups are not interesting when
               -- doing a RECOVER.  So don't stack this action, but do set the
               -- computeRA_restorable flag if we know this
               -- incarnation is an ancestor of the previous one or this is
               -- the current incarnation, and we can apply redo to this full
               -- backup if it would need some.
               IF (isAncestor) THEN
                  rcvRecTop(lastAction);
                  IF (not redoNeeded(action) OR
                      canAddRedo(isAncestor,
                                 action.toSCN_act, action.rlgSCN_act,
                                 lastAction, partial_rcv, doingRecovery) <>
                      action_OLD_REDO) THEN
                     computeRA_restorable := TRUE;
                  END IF;
               END IF;
               addAction_rc := action_SKIP;
            ELSE                                -- not doing a RECOVER
               addAction_rc := addAction(actionIN      => action,
                                         partial_rcv   => partial_rcv,
                                         isAncestor    => isAncestor,
                                         allCopies     => allCopies,
                                         doingRecovery => doingRecovery);
            END IF;
         ELSE
            ------------------------
            -- UKNOWN ACTION KIND --
            ------------------------
            deb(DEB_IN, 'unknown container type: ' ||
                 to_char(action.type_con) ||
                ' or action type: ' || to_char(action.type_act));
            -- We should signal an internal error here, but we don't have
            -- that ability from PLSQL.  So just raise 20999.
            deb(DEB_EXIT, 'with error 20999');
            raise_application_error(-20999, 'unknown action kind');
         END IF;                                -- "switch" on ACTION.KIND
         ---------------------------------------------
         -- Handle the return code from addAction() --
         ---------------------------------------------
         deb(DEB_IN, 'addAction returned code ' || to_char(addAction_rc));
         IF (addAction_rc = action_OK) THEN     -- the action was added
            --------------------------------------
            -- Check for terminating conditions --
            --------------------------------------
            IF (rcvRecStackState.savePoint > 0 AND
                computeRA_allRecords = FALSE#) THEN
               -- If we now have a fullKind action and we are not looking
               -- for all records, then we are done.  Note that this must
               -- be a RESTORE because savePoint is never non-zero if we are
               -- doing RECOVER because fullKind actions are discarded
               -- by RECOVER.
               deb(DEB_IN, 'savePoint > 0' ||
                   ' and computeRA_allRecords = FALSE#');
               done := TRUE;
               EXIT action_loop;
            END IF;
            IF (df_ckpscn is not null) THEN             -- if doing RECOVER
               IF (action.type_con = offlineRangeRec_con_t) THEN
                  -- For offline ranges, the datafile must be checkpointed
                  -- precisely at the offline range start SCN.
                  IF (df_ckpscn = action.fromSCN_act) THEN
                     done := TRUE;
                     EXIT action_loop;
                  END IF;
               ELSE
                  -- For any other action, it is sufficient if the datafile
                  -- is checkpointed >= the action's from_scn.
                  IF (df_ckpscn >= action.fromSCN_act) THEN
                     done := TRUE;
                     EXIT action_loop;
                  END IF;
               END IF;
            END IF;
            ----------------------------------------
            -- Offline Range Spanning a Resetlogs --
            ----------------------------------------
            -- If the action was an offline range and this offline range
            -- started before the current resetlogs, then we must search the
            -- previous incarnation.
            IF (action.type_con = offlineRangeRec_con_t AND
                action.fromSCN_act < dbinc_rlgscn) THEN
               deb(DEB_IN, 'offline range spanning a resetlogs');
               -- This action is the last action we will fetch from this
               -- incarnation.  There cannot be any other actions from this
               -- incarnation with a lower toSCN.  Incremental backups cannot
               -- span resetlogs, and any full backup checkpointed at the end
               -- of the offline range would have been returned from the
               -- cursor already because full backups have a fromSCN of 0.
               -- Get parent's dbinc key --
               SELECT parent_dbinc_key
                 INTO parentDbincKey
                 FROM dbinc
                WHERE dbinc.dbinc_key = computeRecoveryActions.dbinc_key;
               IF (parentDbincKey is null) THEN -- we don't know our parent
                  -- Open a cursor to get all dbinc rows for this database
                  -- that could possibly be our parent incarnation.  We will
                  -- search them all.  If exactly one turns out to work,
                  -- then we assume it is our parent.  If more than one works,
                  -- then we cannot decide and will fail.  If none works, well
                  -- too bad.
                  deb(DEB_OPEN, 'dbinc_cursor');
                  OPEN dbinc_cursor(this_db_key, dbinc_rlgscn);
                  deb(DEB_PRINT, 'doing scan of all possible parent incarnations, top=' ||
                      to_char(rcvRecStack.last));
                  <<dbinc_loop>>
                  LOOP
                     FETCH dbinc_cursor
                      INTO dbinc_row;
                     EXIT WHEN dbinc_cursor%NOTFOUND;
                     deb(DEB_PRINT, 'starting test search of incarnation key=' ||
                         to_char(dbinc_row.dbinc_key));
                     savedrcvRecStackState := rcvRecStackState;
                     rcvRecStackState.top := rcvRecStack.last;
                     rc := computeRecoveryActions(fno, crescn,
                                                  df_rlgscn, df_rlgtime,
                                                  df_ckpscn,
                                                  offlscn,
                                                  onlscn, onltime,
                                                  cleanscn,
                                                  clean2scn, clean2time,
                                                  allowfuzzy, partial_rcv,
                                    rcvRecStack(rcvRecStack.count).fromSCN_act,
                                                  dbinc_row.dbinc_key,
                                                  cf_scn, cf_cretime,
                                                  cf_offrrid,
                                                  TRUE, done_flag, allCopies);
                     -- Trim any actions that may have gotten stacked in
                     -- the test search.  If rc was FALSE, then none should
                     -- have been stacked, but it doesn't hurt to do a
                     -- trim(0), so do it anyway.
                     deb(DEB_PRINT, 'last=' || to_char(rcvRecStack.last) ||
                         ' trimming last ' ||
                         to_char(rcvRecStack.last - rcvRecStackState.top)
                        );
                     rcvRecStack.trim(rcvRecStack.last - rcvRecStackState.top);
                     rcvRecStackState := savedrcvRecStackState;
                     deb(DEB_PRINT, 'count is now ' || to_char(rcvRecStack.count));
                     IF (rc) THEN
                        -- We found an action with a checkpoint SCN that
                        -- matched the offline range start SCN.  So we just
                        -- searched what was most likely our parent
                        -- incarnation.  It is possible that the datafile went
                        -- offline clean at the same SCN in two different
                        -- incarnations.  This is very unlikely, but if it
                        -- happens, then there is no way for us to decide
                        -- which incarnation was the correct one.  So save the
                        -- dbinc_key, trim back any actions we may have added,
                        -- and continue the search.  If we exhaust the
                        -- dbinc_cursor and find only 1 incarnation that
                        -- worked, we can assume it was the right one.
                        -- If we find more than one, then we have to give up.
                        IF (parentDbincKey is null) THEN
                           parentDbincKey := dbinc_row.dbinc_key;
                        ELSE
                           -- We've found a second incarnation that could be
                           -- our parent.  Since we cannot distintuish between
                           -- them, we are done.
                           deb(DEB_PRINT, 'aborting search due to ambiguous ancestory');
                           CLOSE dbinc_cursor;
                           EXIT action_loop;
                        END IF;
                     END IF;
                  END LOOP;     -- dbinc_loop
               END IF;          -- if we don't know our parent
               -- If we know our parent from the catalog or just found our
               -- parent in the search above, then search our parent.
               IF (parentDbincKey is not null) THEN
                  deb(DEB_PRINT, 'starting search of parent incarnation key='||
                      to_char(parentDbincKey));
                  rc := computeRecoveryActions(fno, crescn,
                                               df_rlgscn, df_rlgtime,
                                               df_ckpscn,
                                               offlscn,
                                               onlscn, onltime,
                                               cleanscn,
                                               clean2scn, clean2time,
                                               allowfuzzy, partial_rcv,
                                     rcvRecStack(rcvRecStack.last).fromSCN_act,
                                               parentDbincKey,
                                               cf_scn, cf_cretime,
                                               cf_offrrid,
                                               FALSE, done_flag, allCopies);
                  IF (done_flag) THEN
                     done := TRUE;
                  END IF;
                  IF (action.type_act = spanningRange_act_t) THEN
                     -- We went recursive because of an offline range which
                     -- spanned multiple resetlogs.  In this case, we
                     -- propagate the return code from the recursive search.
                     -- The incarnation we are currently searching is an
                     -- ancestor if the incarnation we just searched
                     -- recursively is an ancestor.
                     isAncestor := rc;
                  END IF;
               END IF;          -- we know or found our parent
               EXIT action_loop;
            END IF;             -- offline range start SCN < dbinc_rlgscn
         ELSIF (addAction_rc = action_FAIL) THEN         -- FAIL
            -- Cannot apply this action for some reason.  That's OK,
            -- there may be other actions that we can apply.
            NULL;
         ELSIF (addAction_rc = action_SKIP) THEN        -- SKIP
            -- We don't want to add this action to the stack.
            NULL;
         ELSIF (addAction_rc = action_OLD_REDO) THEN    -- OLD_REDO
            -- If OLD_REDO, then the to_scn of this action does not reach the
            -- from_scn of the last stacked action, and we are searching an
            -- ancestral incarnation where we cannot apply redo.  We know we
            -- will not see any actions with a higher to_scn, so this stops
            -- our search.  No other actions from this incarnation are usable
            -- because we cannot reach the spanning offline range from them.
            EXIT action_loop;
         ELSE                                   -- unknown return code
            deb(DEB_EXIT, 'with error 20999');
            raise_application_error(-20999, 'unknown add action return code');
         END IF;
      ELSE                                      -- r_act_cv exhausted
         deb(DEB_IN, 'end of cursor reached');
         EXIT action_loop;
      END IF;                                   -- if fetchRecoveryAction
   END LOOP;
   CLOSE r_act_cv;                              -- done with cursor
   IF (done) THEN
      deb(DEB_EXIT);
      RETURN isAncestor;
   END IF;
   -- There is nothing else in this incarnation that we can
   -- restore or apply. If we are doing RECOVER (doingRecovery is TRUE),
   -- then we can just apply redo to this datafile.
   IF (doingRecovery) THEN                      -- if doing RECOVER
      IF (rcvRecStack.count > 0) THEN           -- if found some action
         -- Add a redo action to go from the datafile's checkpoint up to
         -- the from_scn of the last action we stacked.  If partial_rcv is
         -- FALSE, then addRedo() will trim the actions we stacked because we
         -- cannot use them.
         rcvRecTop(lastAction);
         addRedo_rc := addRedo(isAncestor, df_ckpscn, df_rlgscn,
                               lastAction, partial_rcv, doingRecovery);
         IF (addRedo_rc = action_OK OR addRedo_rc = action_FAIL) THEN
            -- OK means we could do the partial recovery from the datafile
            -- checkpoint up to the first action we found.  FAIL means
            -- we could not add the redo, but we don't really need to apply
            -- any.  In either case, the file can be successfully recovered.
            done := TRUE;
         END IF;
      ELSE
         deb(DEB_IN, 'no actions stacked');
         -- We didn't stack any actions.  So this datafile is recoverable only
         -- if is from the current incarnation.  Set the done flag accordingly.
         IF (df_rlgscn = this_reset_scn AND
             df_rlgtime = this_reset_time) THEN
            done := TRUE;
         END IF;
      END IF;
   ELSE                                         -- not doing a RECOVER
      -- We may decide to trim the stack here.  Never trim beyond the top
      -- of the stack.  The top is normally 0, but it is non-zero when
      -- we are making a test search to find our parent incarnation.
      IF (rcvRecStackState.savePoint = 0) THEN
         -- We did not find any fullKind actions that we could apply.
         -- This means we cannot restore this file or there is nothing
         -- interesting to list.  Note that we may have some actions
         -- stacked at this point, but they are not useful.
         -- Here is where we could do a CREATE DATAFILE.
         deb(DEB_IN, 'could try create datafile');
         rcvRecStack.trim(rcvRecStack.count - rcvRecStackState.top);
                                                  -- purge all actions
      ELSE
         -- We found at least 1 fullKind action, so the file is
         -- definitly restorable or there is something interesting to LIST.
         -- No actions stacked after the savePoint are usable though because
         -- there is no fullKind backup to which we could apply these
         -- actions. So trim all actions up to the savePoint.
         deb(DEB_IN, 'trim all actions after savePoint='||
                to_char(greatest(rcvRecStackState.savePoint,
                                 rcvRecStackState.top)));
         rcvRecStack.trim(rcvRecStack.last -
                          greatest(rcvRecStackState.savePoint,
                                   rcvRecStackState.top));
         done := TRUE;
      END IF;
   END IF;                                      -- if doing recover
   IF (done) THEN
      deb(DEB_IN, 'done is TRUE');
   ELSE
      deb(DEB_IN, 'done is FALSE');
   END IF;
   deb(DEB_EXIT);
   RETURN isAncestor;
END computeRecoveryActions;
----------------------------- trimRecoveryActions -----------------------------
FUNCTION trimRecoveryActions(
   maxActions           IN number
  ,containerMask        IN number
  ,actionMask           IN number)
RETURN NUMBER IS
   dummy     rcvRec_t;
   remaining number;
BEGIN
   deb(DEB_ENTER, 'trimRecoveryActions[function]');
   IF (rcvRecStack.count > 0) THEN
      rcvRecPop(dummy);
      remaining := trimRecoveryActions(maxActions, containerMask, actionMask);
      -- If this record is one that would be selected by the masks in effect,
      -- then we can keep it if the remaining records on the
      -- the stack after trimming are less than the maxActions limit.
      -- Note:  if other kinds of filtering are going to occur in
      -- getRecoveryAction, then that filtering should also be done here
      -- so that we don't count a record that won't be seen by the client.
      -- NOTE: In case that actionMask is full_act_t we will skip
      --       "keep" backups.
      IF ((bitand(dummy.type_con, containerMask) = 0) OR
           (bitand(dummy.type_act, actionMask) = 0)   OR
           ((bitand(actionMask, full_act_t) <> 0) AND
            (dummy.keep_options <> KEEP_NO))) THEN
         -- This record is not selected by the masks in effect or
         -- or it is "keep" backup, so we keep it on the stack.
         rcvRecPush(dummy);
         deb(DEB_EXIT, 'with: '||to_char(remaining));
         RETURN remaining;
      ELSE
         IF (remaining < maxActions) THEN
            rcvRecPush(dummy);          -- put back on stack
            deb(DEB_EXIT, 'with: '||to_char(remaining+1));
            RETURN remaining + 1;
         ELSE
            -- Cannot keep it.
            deb(DEB_IN, 'deleting action:');
            printRcvRec(dummy);
            deb(DEB_EXIT, 'with: '||to_char(remaining));
            RETURN remaining;
         END IF;
      END IF;
   ELSE
      deb(DEB_EXIT, 'with: 0');
      RETURN 0;
   END IF;
END trimRecoveryActions;
----------------------------- printinCorebsRec --------------------------------
PROCEDURE printinCorebsRec(
   inCorebsRec  IN  inCorebsRec_t)
IS
BEGIN
   deb(DEB_PRINT, 'bsKey= ' || nvl(to_char(inCorebsRec.bsKey), 'NULL') ||
       ' dev= ' || nvl(inCoredeviceList(inCorebsRec.devindx), 'NULL'));
   -- Too much debug information will cause buffer overflow
   -- deb(DEB_PRINT, 'setStamp= '   || to_char(inCorebsRec.setStamp));
   -- deb(DEB_PRINT, 'setCount= '   || to_char(inCorebsRec.setCount));
   -- deb(DEB_PRINT, 'pieceCount= ' || to_char(inCorebsRec.pieceCount));
END printinCorebsRec;
---------------------------- getinCoreDeviceType ------------------------------
-- Push the device type if it doesn't exists in the stack and
-- return the index. Otherwise just return the index.
--
FUNCTION getinCoreDeviceType(
   deviceType IN varchar2)
RETURN NUMBER IS
BEGIN
   FOR i IN 1..inCoredeviceCount LOOP
      IF deviceType = inCoredeviceList(i) THEN
         RETURN i;
      END IF;
   END LOOP;
   inCoredeviceCount := inCoredeviceCount + 1;
   inCoredeviceList(inCoredeviceCount) := deviceType;
   RETURN inCoredeviceCount;
END getinCoreDeviceType;
-----------------------------resetIncoreData----------------------------------
PROCEDURE resetIncoreData
IS
BEGIN
   IF (inCorebsRecStack.count > 0) THEN
      inCorebsRecStack.delete;
      inCorebsRecStack.trim(inCorebsRecStack.count);   -- clear stack
   END IF;
   IF (inCoredeviceCount > 0) THEN
      inCoredeviceList.delete;
   END IF;
   inCoredeviceCount := 0;                             -- clear device index
END resetIncoreData;
---------------------------- inCorebsRecPush ----------------------------------
PROCEDURE inCorebsRecPush(
   inCorebsRec IN inCorebsRec_t)
IS
   new   number;
BEGIN
   inCorebsRecStack.extend;
   inCorebsRecStack(inCorebsRecStack.last) := inCorebsRec;
EXCEPTION
   WHEN others THEN
      deb(DEB_PRINT, 'caught exception during inCorebsRecPush count ' ||
                      inCorebsRecStack.count);
      deb(DEB_EXIT, substr(sqlerrm, 1, 512));
      raise;
END inCorebsRecPush;
----------------------------- inCorebsRecGet ----------------------------------
PROCEDURE inCorebsRecGet(
   indx          IN  number
  ,inCorebsRec   OUT inCorebsRec_t)
IS
BEGIN
   inCorebsRec := inCorebsRecStack(indx);
END inCorebsRecGet;
----------------------------- inCorebsRecTop ----------------------------------
PROCEDURE inCorebsRecTop(
   inCorebsRec OUT inCorebsRec_t)
IS
BEGIN
   IF (inCorebsRecStack.count = 0) THEN
      inCorebsRec := NULL;
   ELSE
      inCorebsRecGet(inCorebsRecStack.count, inCorebsRec);
   END IF;
END inCorebsRecTop;
----------------------------- inCorebsRecPop ----------------------------------
PROCEDURE inCorebsRecPop(
   inCorebsRec OUT inCorebsRec_t)
IS
BEGIN
   inCorebsRecTop(inCorebsRec);
   inCorebsRecStack.trim;
END inCorebsRecPop;
----------------------------qukvalidateBackupSet-------------------------------
-- quick validate backup set
FUNCTION qukvalidateBackupSet(
   bsKey       IN number)
RETURN BOOLEAN IS
  bottom    number;
  mid       number;
  top       number;
  found     boolean := FALSE;    -- not found yet
BEGIN
   deb(DEB_ENTER, 'qukvalidateBackupSet: ' || to_char(bsKey));
   IF (inCorebsRecStack.count > 0) THEN
      -- Since the stack is ordered by bskey, we will make use of that
      -- to quickly search a given key
      ---------------------
      --- Binary search ---
      ---------------------
      bottom := 1;
      top    := inCorebsRecStack.count;
      WHILE (NOT found) LOOP
         mid := floor((top + bottom)/2);   -- should never exceed top
         IF (inCorebsRecStack(mid).bsKey = bsKey) THEN
            found := TRUE;
         ELSIF (inCorebsRecStack(mid).bsKey < bsKey) THEN
            bottom := mid;
         ELSE
            top := mid;
         END IF;
         IF ((bottom + 1)>= top) THEN
            -- since we floored we mayn't have compared the top and bottom
            IF (inCorebsRecStack(top).bsKey = bsKey  OR
                inCorebsRecStack(bottom).bsKey = bsKey) THEN
               found := TRUE;
            END IF;
            EXIT;
         END IF;
      END LOOP;
   END IF;
   IF found THEN
      deb(DEB_EXIT, 'with: TRUE');
   ELSE
      deb(DEB_EXIT, 'with: FALSE');
   END IF;
   RETURN found;
EXCEPTION
   WHEN others THEN
      deb(DEB_PRINT, 'caught exception during qukvalidateBackupSet');
      deb(DEB_PRINT, ' top = '       || to_char(top)    ||
                     ' mid = '       || to_char(mid)    ||
                     ' bottom= '     || to_char(bottom) ||
                     ' stackcount= ' || to_char(inCorebsRecStack.count));
      deb(DEB_EXIT, substr(sqlerrm, 1, 512));
      raise;
END qukvalidateBackupSet;
--------------------------- createinCorebsRecStack ----------------------------
PROCEDURE createinCorebsRecStack(
   backupType             IN binary_integer
  ,tag                    IN varchar2     DEFAULT NULL
  ,statusMask             IN number
  ,checkDeviceIsAllocated IN boolean      DEFAULT TRUE
  ,completedAfter         IN date         DEFAULT NULL
  ,completedBefore        IN date         DEFAULT NULL)
IS
   local        inCorebsCursor_t;
   inCorebsRec  inCorebsRec_t;
BEGIN
   deb(DEB_ENTER, 'createinCorebsRecStack' || to_date(sysdate));
   IF (inCorebsRec_c%ISOPEN) THEN
      CLOSE inCorebsRec_c;
   END IF;
   resetIncoreData;    -- clear all inCore data structures
   OPEN inCorebsRec_c(backupType             => backupType
                     ,tag                    => tag
                     ,statusMask             => statusMask
                     ,completedAfter         => completedAfter
                     ,completedBefore        => completedBefore);
   LOOP
      <<nextRow>>
      FETCH inCorebsRec_c INTO local;
      EXIT WHEN inCorebsRec_c%NOTFOUND;
      IF (checkDeviceIsAllocated AND
          isDeviceTypeAllocated(local.deviceType) = FALSE#) THEN
         GOTO nextRow;
      END IF;
      -- form a inCorebsRec
      inCorebsRec.bsKey      := local.bsKey;
      inCorebsRec.setStamp   := local.setStamp;
      inCorebsRec.setCount   := local.setCount;
      inCorebsRec.devindx    := getinCoreDeviceType(local.deviceType);
      inCorebsRec.pieceCount := local.pieceCount;
      inCorebsRecPush(inCorebsRec);
   END LOOP;
   CLOSE inCorebsRec_c;
   deb(DEB_PRINT, 'inCorebsRecStack.count: ' ||
                   to_char(inCorebsRecStack.count));
   -- print the entire incore stack
   IF (debug AND inCorebsRecStack.count > 0) THEN
      deb(DEB_PRINT, '*********START DUMPING INCORE BSREC STACK**********');
      FOR this in 1..inCorebsRecStack.count LOOP
         inCorebsRecGet(this, inCorebsRec);
         printinCorebsRec(inCorebsRec);
      END LOOP;
      deb(DEB_PRINT, '***********END DUMPING INCORE BSREC STACK**********');
   END IF;
EXCEPTION
   WHEN others THEN
      deb(DEB_PRINT, 'caught exception during createinCorebsRecStack');
      deb(DEB_EXIT, substr(sqlerrm, 1, 512));
      raise;
END createinCorebsRecStack;
-----------------------------------------------
-- *** PUBLIC FUNCTION/PROCEDURE SECTION *** --
-----------------------------------------------
---------------
-- Debugging --
---------------
---------------------------------- dumpState ----------------------------------
FUNCTION dumpState(
   lineno IN number)
RETURN varchar2 IS
BEGIN
   IF    lineno = 1 THEN RETURN 'this_db_key='||this_db_key;
   ELSIF lineno = 2 THEN RETURN 'this_dbinc_key='||this_dbinc_key;
   ELSIF lineno = 3 THEN RETURN 'this_reset_scn='||this_reset_scn;
   ELSIF lineno = 4 THEN RETURN 'this_reset_time='||this_reset_time;
   ELSIF lineno = 5 THEN RETURN 'untilSCN='||untilSCN;
   ELSIF lineno = 6 THEN RETURN 'untilTime='||untilTime;
   ELSIF lineno = 7 THEN RETURN 'getRA_completedAfter='||getRA_completedAfter;
   ELSIF lineno = 8 THEN RETURN
      'getRA_completedBefore='||getRA_completedBefore;
   ELSIF lineno = 9 THEN RETURN 'getRA_likePattern='||getRA_likePattern;
   ELSIF lineno = 10 THEN RETURN 'getRA_containerMask='||getRA_containerMask;
   ELSIF lineno = 11 THEN RETURN 'getRA_actionMask='||getRA_actionMask;
   ELSIF lineno = 12 THEN RETURN 'computeRA_allRecords='||computeRA_allRecords;
   ELSIF lineno = 13 THEN RETURN 'allIncarnations='||allIncarnations;
   ELSE RETURN NULL;
   END IF;
END dumpState;
---------------------------------- setDebugOn ---------------------------------
PROCEDURE setDebugOn
IS
BEGIN
   debug := TRUE;
END setDebugOn;
--------------------------------- setDebugOff ---------------------------------
PROCEDURE setDebugOff
IS
BEGIN
   debug := FALSE;
END setDebugOff;
----------------------------
-- Package Initialization --
----------------------------
-- This is a vestigal function that was released to customers in 8.1.3 Beta.
-- It is no longer called, and is no longer needed, but must still be here
-- because this version of the package may be called by an 8.1.3 rman
-- executable.
---------------------------------- initialize ---------------------------------
PROCEDURE initialize(
   rman_vsn IN number)
IS
BEGIN
   NULL;
END initialize;
---------------------------- set_package_constants ----------------------------
PROCEDURE set_package_constants
IS
BEGIN
   -- This procedure exists only for backwards compatibility with RMAN 8.1.5.
   -- This package no longer cares what the values are.  The rddf cursor
   -- now implements the order-by for preference using hard-coded values
   -- that are not returned to the client.
   NULL;
END set_package_constants;
-----------------------
-- Utility functions --
-----------------------
---------------------------------- stamp2date ---------------------------------
FUNCTION stamp2date(
   stamp IN number)
RETURN date
IS
   x    number;
   dt   varchar2(19);
BEGIN
   x := stamp;
   dt := to_char(mod(x,60), 'FM09'); -- seconds
   x := floor(x/60);
   dt := to_char(mod(x,60), 'FM09') || ':' || dt; -- minutes
   x := floor(x/60);
   dt := to_char(mod(x,24), 'FM09') || ':' || dt; -- hours
   x := floor(x/24);
   dt := to_char(mod(x,31)+1, 'FM09') || ' ' || dt; -- days
   x := floor(x/31);
   dt := to_char(mod(x,12)+1, 'FM09') || '/' || dt; -- months
   dt := to_char(floor(x/12)+1988)   || '/' || dt;
   RETURN to_date(dt, 'YYYY/MM/DD HH24:MI:SS');
END stamp2date;
------------------------------
-- Set Database Incarnation --
------------------------------
--------------------------------- setDatabase ---------------------------------
PROCEDURE setDatabase(
   db_name    IN varchar2
  ,reset_scn  IN number
  ,reset_time IN date
  ,db_id      IN number)
IS
   local        dbinc%rowtype;                    -- local variables
   dbnm         dbinc.db_name%TYPE;
   current_inc  varchar2(3);
   rid          char(18);
BEGIN
   deb(DEB_ENTER, 'setDatabase');
   this_db_key := NULL;                  -- clear in case exception raised
   this_dbinc_key := NULL;
   this_reset_scn := NULL;
   this_reset_time := NULL;
   -- verify that this package is compatible with the recovery catalog
   BEGIN
      SELECT null
        INTO local.db_key
        FROM rcver
       WHERE version = catalogVersion;
   EXCEPTION
      WHEN no_data_found THEN
         deb(DEB_EXIT, 'with error 20299');
         raise_application_error(-20299, 'Recovery catalog version mismatch');
   END;
   -- If the target database is mounted, then we have the db_id (kccfhdbi).
   -- This can be used to find the row in the db table corresponding
   -- to the target database, and it will indicate which incarnation
   -- is currently considered the current one.
   IF (db_id is not NULL) THEN
      deb(DEB_IN, ' db_id=' || to_char(db_id));
      BEGIN
         SELECT db.db_key, curr_dbinc_key, dbinc.reset_scn, dbinc.reset_time
           INTO local.db_key, local.dbinc_key,
                local.reset_scn, local.reset_time
           FROM db, dbinc
          WHERE db_id = setDatabase.db_id       -- should return 1 row
            AND dbinc.dbinc_key = db.curr_dbinc_key;
      EXCEPTION
         WHEN no_data_found THEN
            deb(DEB_EXIT, 'with error 20001');
            raise_application_error(-20001, 'Database not found');
      END;
      -- Validate SCN only only if the target database is indeed mounted
      IF (db_name is NOT NULL) THEN
         -- Now validate that the resetlogs SCN we were passed matches that
         -- of the current incarnation of this database.  If not, then
         -- a reset database should be done, or the wrong controlfile is
         -- mounted.
         BEGIN
            SELECT decode(dbinc.dbinc_key, db.curr_dbinc_key, 'YES', 'NO'),
                   dbinc.db_name, dbinc.rowid
              INTO current_inc,
                   dbnm,
                   rid
              FROM db, dbinc
             WHERE db.db_key = dbinc.db_key
               AND db.db_id = setDatabase.db_id
--               AND dbinc.db_name = setDatabase.db_name
               AND dbinc.reset_scn = setDatabase.reset_scn
               AND dbinc.reset_time = setDatabase.reset_time;
         EXCEPTION
            WHEN no_data_found THEN
               deb(DEB_EXIT, 'with error 20003');
               raise_application_error(-20003,
                                       'Database incarnation not found');
         END;
         IF (current_inc = 'NO') THEN
            deb(DEB_EXIT, 'with error 20011');
            raise_application_error(-20011,
                                    'Database incarnation not current');
         END IF;
         IF (dbnm != setDatabase.db_name) THEN
            deb(DEB_PRINT, 'DB_NAME changed from '||dbnm||' to '||
                           setDatabase.db_name);
            UPDATE dbinc
               SET dbinc.db_name = setDatabase.db_name
             WHERE rowid = rid;
            COMMIT;
         END IF;
      END IF;
   ELSIF (db_name is NOT NULL) THEN
      -- If db_id is unknown, try using db_name
      deb(DEB_IN, 'db_id is null');
      BEGIN
         SELECT db.db_key, db.curr_dbinc_key, dbinc.reset_scn, dbinc.reset_time
           INTO local.db_key, local.dbinc_key,
                local.reset_scn, local.reset_time
           FROM db, dbinc
          WHERE db.curr_dbinc_key = dbinc.dbinc_key
            AND dbinc.db_name = setDatabase.db_name;
      EXCEPTION
         WHEN no_data_found THEN
            deb(DEB_EXIT, 'with error 20001');
            raise_application_error(-20001, 'Database not found');
         WHEN too_many_rows THEN
            deb(DEB_EXIT, 'with error 20005');
            raise_application_error(-20005, 'Database name is ambiguous');
      END;
   ELSE
      deb(DEB_EXIT, 'with error 20006');
      raise_application_error(-20006, 'Database name is missing');
   END IF;
   this_db_key := local.db_key;
   this_dbinc_key := local.dbinc_key;
   this_reset_scn := local.reset_scn;
   this_reset_time := local.reset_time;
   deb(DEB_EXIT);
END setDatabase;
--------------------------------- setDbincKey ---------------------------------
PROCEDURE setDbincKey(
   key IN number)
IS
BEGIN
   deb(DEB_ENTER, 'setDbincKey');
   IF (key is not null) THEN
      this_dbinc_key := key;
   ELSE
      -- if this query gets more than 1 row, than you lose.  try again.
      SELECT curr_dbinc_key
        INTO this_dbinc_key
        FROM db;
   END IF;
   SELECT db_key, reset_scn
     INTO this_db_key, this_reset_scn
     FROM dbinc
    WHERE dbinc_key = this_dbinc_key;
   deb(DEB_EXIT);
END setDbincKey;
----------------------------- getParentIncarnation ----------------------------
FUNCTION getParentIncarnation(
   resetlogs_change# IN OUT number
  ,resetlogs_time    IN OUT date)
RETURN number IS
BEGIN
   deb(DEB_ENTER, 'getParentIncarnation');
   -- If input is null, this is the first call, and we return the current
   -- incarnation's key.
   IF (resetlogs_change# is null) THEN
      getParentIncarnationKey := this_dbinc_key;
   END IF;
   SELECT resetlogs_change#, resetlogs_time, parent_dbinc_key
     INTO resetlogs_change#, resetlogs_time, getParentIncarnationKey
     FROM rc_database_incarnation where dbinc_key = getParentIncarnationKey;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
END getParentIncarnation;
-------------------------------- getCheckpoint --------------------------------
PROCEDURE getCheckpoint(
   scn OUT number
  ,seq OUT number
  ,ckp_key_1 OUT number
  ,ckp_key_2 OUT number)
IS
  full_row   ckp%ROWTYPE;
  either_row ckp%ROWTYPE;
BEGIN
   deb(DEB_ENTER, 'getCheckpoint');
   IF (this_dbinc_key is NULL) THEN
     deb(DEB_EXIT, 'with error 20020');
     raise_application_error(-20020, 'Database incarnation not set');
   END IF;
   -- Return the SCN and controlfile sequence from the ckp table row
   -- with the greatest ckp_scn and same high_df_recid as the most recent FULL
   -- checkpoint.
   -- The first query finds the FULL ckp with the greatest ckp_scn.
   -- If there are 2 FULL checkpoints with the same ckp_scn, we choose the
   -- one with the highest cf_seq or the highest cf_create_time.
   -- The second query finds the row of either ckp_type with the highest
   -- ckp_scn for the high_df_recid and cf_create_time obtained in the
   -- previous query.  If there are 2 rows with the same ckp_scn for a
   -- given recid and create_time, then we choose the one with the highest
   -- cf_seq.  If the cf_seq is the same, then the ckp_type columns *must*
   -- differ because of the ckp_u1 constraint.  In this unlikely case, we
   -- choose the 'PARTIAL' one.
   -- If the first query returns no rows, then it's not necessary to execute
   -- the second query, but it does no harm, and there are probably no rows in
   -- the ckp table for this dbinc_key anyway.  If the first query does return
   -- a row, then the second query will *always* return a row.
   FOR r IN (SELECT /*+ first_rows */ * FROM ckp
             WHERE dbinc_key = this_dbinc_key AND
                   ckp_type  = 'FULL'
             ORDER BY ckp_scn DESC, cf_create_time DESC, ckp_cf_seq DESC)
   LOOP
     full_row := r;
     EXIT;
   END LOOP;
   FOR r IN (SELECT /*+ first_rows */ * FROM ckp
             WHERE dbinc_key      = this_dbinc_key AND
                   high_df_recid  = full_row.high_df_recid AND
                   cf_create_time = full_row.cf_create_time
             ORDER BY ckp_scn DESC, ckp_cf_seq DESC, ckp_type DESC)
   LOOP
     either_row := r;
     EXIT;
   END LOOP;
   IF either_row.ckp_key IS NOT NULL THEN
      scn       := either_row.ckp_scn;
      seq       := either_row.ckp_cf_seq;
      ckp_key_1 := full_row.ckp_key;
      ckp_key_2 := either_row.ckp_key;
   ELSE
      scn       := 0;
      seq       := 0;
      ckp_key_1 := 0;
      ckp_key_2 := 0;
   END IF;
   deb(DEB_EXIT);
END getCheckpoint;
PROCEDURE getCheckpoint(
   scn OUT number
  ,seq OUT number)
IS
   ckp_key_1 number;
   ckp_key_2 number;
BEGIN
   getCheckpoint(scn, seq, ckp_key_1, ckp_key_2);
END getCheckpoint;
-------------------
-- Query Filters --
-------------------
------------------------------ setCompletedRange ------------------------------
PROCEDURE setCompletedRange(
   after  IN date
  ,before IN date)
IS
BEGIN
   getRA_completedAfter  := after;
   getRA_completedBefore := before;
END setCompletedRange;
-------------------------------- setLikePattern -------------------------------
PROCEDURE setLikePattern(
   pattern IN varchar2)
IS
BEGIN
   getRA_likePattern := pattern;
END setLikePattern;
------------------------------ setAllIncarnations -----------------------------
PROCEDURE setAllIncarnations(
   flag IN boolean)
IS
BEGIN
   IF (flag) THEN
      allIncarnations := TRUE#;
   ELSE
      allIncarnations := FALSE#;
   END IF;
END setAllIncarnations;
-- Obsolete as of 8.1.6
---------------------------------- setAllFlag ---------------------------------
PROCEDURE setAllFlag(
   flag IN boolean)
IS
BEGIN
   setAllIncarnations(flag);
   IF (flag) THEN
      ignoreCreationSCN := TRUE#;
   ELSE
      ignoreCreationSCN := FALSE#;
   END IF;
END setAllFlag;
--------------------------------- setUntilTime --------------------------------
PROCEDURE setUntilTime(
   unttime IN date)
IS
    walk_dbinc_key  number := NULL;
    parent_dbinc_key  number := NULL;
BEGIN
   deb(DEB_ENTER, 'setUntilTime');
   IF (this_dbinc_key is NULL) THEN
      deb(DEB_EXIT, 'with error 20020');
      raise_application_error(-20020, 'Database incarnation not set');
   END IF;
   walk_dbinc_key := this_dbinc_key;
<<parent_inc>>
   untilSCN  := NULL;
   untilTime := unttime;
   BEGIN
      SELECT resetlogs_change#
         INTO untilSCN
         FROM rc_database
      WHERE dbinc_key = walk_dbinc_key
         AND resetlogs_time <= untilTime;
   EXCEPTION
      WHEN no_data_found THEN
         BEGIN
            IF (allIncarnations = TRUE#) THEN
               SELECT parent_dbinc_key
                  INTO parent_dbinc_key
                  FROM dbinc
               WHERE dbinc.dbinc_key = walk_dbinc_key;
               walk_dbinc_key := parent_dbinc_key;
               IF (walk_dbinc_key IS NULL) THEN
                  deb(DEB_IN, 'parent_dbinc_key=NULL -> exiting');
                  untilSCN := 0;                         -- begining of world
               ELSE
                  deb(DEB_IN, 'parent_dbinc_key=' ||
                     to_char(parent_dbinc_key));
                  GOTO parent_inc;           -- get scn of parent incarnation
               END IF;
            ELSE
               deb(DEB_EXIT, 'with error 20007');
               raise_application_error(-20207,
                                 'until time is before resetlogs time');
            END IF;
         END;
   END;
   -- find the highest SCN that is associated with a timestamp less than or
   -- equal to the untilTime. This will give us an approximation of the SCN
   -- where point-in-time recovery will stop and we use it to limit the
   -- candidates for restore to backups and copies that are not fuzzy at the
   -- SCN.
   computeUntilSCN(untilTime, untilSCN);
   deb(DEB_EXIT, 'untilSCN='||to_char(untilSCN));
END setUntilTime;
--------------------------------- setUntilScn ---------------------------------
PROCEDURE setUntilScn(
   scn IN number)
IS
BEGIN
   deb(DEB_ENTER, 'setUntilSCN');
   untilSCN := scn;
   untilTime := NULL;
   IF (this_dbinc_key is NULL) THEN
      deb(DEB_EXIT, 'with error 20020');
      raise_application_error(-20020, 'Database incarnation not set');
   END IF;
   BEGIN
      SELECT untilSCN
        INTO untilSCN
        FROM rc_database
       WHERE dbinc_key = this_dbinc_key
         AND resetlogs_change# <= untilSCN;
   EXCEPTION
      WHEN no_data_found THEN
         deb(DEB_EXIT, 'with error 20008');
         raise_application_error(-20208, 'until SCN is before resetlogs SCN');
   END;
   deb(DEB_EXIT);
END setUntilScn;
--------------------------------- setUntilLog ---------------------------------
PROCEDURE setUntilLog(
   sequence# IN number
  ,thread#   IN number)
IS
BEGIN
   deb(DEB_ENTER, 'setUntilLog');
   untilTime := NULL;
   untilSCN := NULL;
   IF (this_dbinc_key is NULL) THEN
      deb(DEB_EXIT, 'with error 20020');
      raise_application_error(-20020, 'Database incarnation not set');
   END IF;
   IF (sequence# is NULL) THEN
      deb(DEB_EXIT, 'with error 20205');
      raise_application_error(-20205, 'Incomplete UNTIL clause');
   END IF;
   BEGIN
      -- set untilSCN to the low SCN of the specified log
      SELECT first_change#
        INTO untilSCN
        FROM rc_log_history
       WHERE dbinc_key = this_dbinc_key
         AND thread# = nvl(setUntilLog.thread#, 1)  -- default thread# is 1
         AND sequence# = setUntilLog.sequence#;
   EXCEPTION
      WHEN no_data_found THEN
         BEGIN
            -- the specified log is not (yet?) in the recovery catalog.
            -- try setting untilSCN to the next SCN of the previous log
            SELECT next_change#
              INTO untilSCN
              FROM rc_log_history
             WHERE dbinc_key = this_dbinc_key
               -- default thread# is 1
               AND thread# = nvl(setUntilLog.thread#, 1)
               AND sequence# = setUntilLog.sequence# - 1;
         EXCEPTION
            WHEN no_data_found THEN
               deb(DEB_EXIT, 'with error 20206');
               raise_application_error(-20206, 'Specified log does not exist');
         END;
   END;
   deb(DEB_EXIT);
END setUntilLog;
--------------------------------- getUntilTime --------------------------------
FUNCTION getUntilTime
RETURN date IS
BEGIN
   RETURN untilTime;
END getUntilTime;
--------------------------------- getUntilScn ---------------------------------
FUNCTION getUntilScn
RETURN number IS
BEGIN
   RETURN untilScn;
END getUntilScn;
---------------------------------- resetUntil ---------------------------------
PROCEDURE resetUntil
IS
BEGIN
   untilSCN := NULL;
   untilTime := NULL;
END resetUntil;
----------------------------------- setFrom -----------------------------------
PROCEDURE setFrom(
   restorefrom IN number DEFAULT NULL)
IS
BEGIN
   IF (restorefrom in (BACKUP, COPY) OR restorefrom is NULL) THEN
      restoreSource := restorefrom;
   ELSE
      raise_application_error(-20200, 'Invalid restore source');
   END IF;
END setFrom;
-------------------------------- setDeviceType --------------------------------
PROCEDURE setDeviceType(
   type IN varchar2)
IS
BEGIN
   IF (deviceCount >= 8) THEN
      raise_application_error(-20280, 'Too many device types');
   END IF;
   deviceCount := deviceCount + 1;
   deviceList(deviceCount) := type;
   IF (type = 'DISK') THEN
      diskDevice := TRUE;
   END IF;
END setDeviceType;
----------------------------------- setStandby  ------------------------------
PROCEDURE setStandby(
   stby IN boolean)
IS
BEGIN
   if stby is NULL then
      onlyStandby := NULL;
   elsif stby then
      onlyStandby := TRUE#;
   else
      onlyStandby := FALSE#;
   end if;
END setStandby;
------------------------------- setDeviceTypeAny ------------------------------
PROCEDURE setDeviceTypeAny
IS
BEGIN
   diskDevice := true;
   anyDevice := true;
   deviceCount := 0;
END setDeviceTypeAny;
------------------------------- resetDeviceType -------------------------------
PROCEDURE resetDeviceType
IS
BEGIN
   FOR i in 1..8 LOOP
      deviceList(i) := NULL;
   END LOOP;
   deviceCount := 0;
   diskDevice := FALSE;
   anyDevice := FALSE;
END resetDeviceType;
------------------------------------ setTag -----------------------------------
PROCEDURE setTag(
   tag IN varchar2 DEFAULT NULL)
IS
BEGIN
   restoreTag := tag;
END setTag;
------------------------------ setTransClause --------------------------------
--
-- For now, we use this only for archivelog translation.
--
PROCEDURE setTransClause(
   thread   IN NUMBER   DEFAULT NULL
  ,fromTime IN DATE     DEFAULT NULL
  ,toTime   IN DATE     DEFAULT NULL
  ,fromSCN  IN NUMBER   DEFAULT NULL
  ,toSCN    IN NUMBER   DEFAULT NULL
  ,fromSeq  IN NUMBER   DEFAULT NULL
  ,toSeq    IN NUMBER   DEFAULT NULL
  ,pattern  IN VARCHAR2 DEFAULT NULL)
IS
BEGIN
   deb(DEB_ENTER, 'setTransClause');
   tc_thread   := thread;
   tc_fromTime := fromTime;
   tc_toTime   := toTime;
   tc_fromSCN  := fromSCN;
   tc_toSCN    := toSCN;
   tc_fromSeq  := fromSeq;
   tc_toSeq    := toSeq;
   tc_pattern  := pattern;
   deb(DEB_IN, 'tc_thread= '   || tc_thread);
   deb(DEB_IN, 'tc_fromSCN= '  || fromSCN);
   deb(DEB_IN, 'tc_toSCN= '    || toSCN);
   deb(DEB_IN, 'tc_fromTime= ' || fromTime);
   deb(DEB_IN, 'tc_toTime= '   || toTime);
   deb(DEB_IN, 'tc_fromSeq= '  || fromSeq);
   deb(DEB_IN, 'tc_toSeq= '    || toSeq);
   deb(DEB_IN, 'tc_pattern= '  || pattern);
   deb(DEB_EXIT);
END setTransClause;
----------------------------------- resetAll ----------------------------------
PROCEDURE resetAll
IS
BEGIN
   -- reset to defaults
   setRAflags(kindMask   => allKind,
              allRecords => FALSE);
   setAllFlag(FALSE);
   setLikePattern(NULL);
   setCompletedRange(after => NULL, before => NULL);
   resetUntil;
   setFrom(NULL);
   resetDeviceType;
   setTag(NULL);                        -- restoreTag := NULL
   setStandby(NULL);
   versionCounter := 1;                 -- for getPackageVersion
   getArchivedLogCursor  := NULL;
   getBackupPieceCursor  := NULL;
   getDatafileCopyCursor := NULL;
   getDatafileCursor     := NULL;
   getProxyCopyCursor    := NULL;
   setTransClause;                      -- reset TransClause
   resetIncoreData;                     -- reset incore data structures
   pname_i := 0;                        -- reset debuging
   IF findControlfileCopy%ISOPEN THEN
      CLOSE findControlfileCopy;
   END IF;
   IF findControlfileProxyCopy%ISOPEN THEN
      CLOSE findControlfileProxyCopy;
   END IF;
   IF findControlfileBackup_c%ISOPEN THEN
      CLOSE findControlfileBackup_c;
   END IF;
   IF findSpfileBackup_c%ISOPEN THEN
      CLOSE findSpfileBackup_c;
   END IF;
   IF findDatafileCopyKey%ISOPEN THEN
      CLOSE findDatafileCopyKey;
   END IF;
   IF findDatafileBackup_c%ISOPEN THEN
      CLOSE findDatafileBackup_c;
   END IF;
   IF findProxyCopy%ISOPEN THEN
      CLOSE findProxyCopy;
   END IF;
   IF findProxyCopyKey%ISOPEN THEN
      CLOSE findProxyCopyKey;
   END IF;
   IF findArchivedLogCopy%ISOPEN THEN
      CLOSE findArchivedLogCopy;
   END IF;
   IF findArcLogBackup%ISOPEN THEN
      CLOSE findArcLogBackup;
   END IF;
   IF findValidBackupSet_c%ISOPEN THEN
      CLOSE findValidBackupSet_c;
   END IF;
   IF findValidBackupSet1P_c%ISOPEN THEN
      CLOSE findValidBackupSet1P_c;
   END IF;
   IF findBackupPiece_c%ISOPEN THEN
      CLOSE findBackupPiece_c;
   END IF;
   IF findBackupPieceBpKey%ISOPEN THEN
      CLOSE findBackupPieceBpKey;
   END IF;
   IF findBackupPieceBsKey%ISOPEN THEN
      CLOSE findBackupPieceBsKey;
   END IF;
   IF translateDatabase_c%ISOPEN THEN
      CLOSE translateDatabase_c;
   END IF;
   IF translateTablespace_c%ISOPEN THEN
      CLOSE translateTablespace_c;
   END IF;
   IF translateDatafileName%ISOPEN THEN
      CLOSE translateDatafileName;
   END IF;
   IF translateDatafileNumber%ISOPEN THEN
      CLOSE translateDatafileNumber;
   END IF;
   IF translateDatafileCheckpoint%ISOPEN THEN
      CLOSE translateDatafileCheckpoint;
   END IF;
   IF translateAllDatafile_c%ISOPEN THEN
      CLOSE translateAllDatafile_c;
   END IF;
   IF translateCorruptList_c%ISOPEN THEN
      CLOSE translateCorruptList_c;
   END IF;
   IF translateOnlineLogs_c%ISOPEN THEN
      CLOSE translateOnlineLogs_c;
   END IF;
   IF translateArcLogKey%ISOPEN THEN
      CLOSE translateArcLogKey;
   END IF;
   IF translateArcLogName%ISOPEN THEN
      CLOSE translateArcLogName;
   END IF;
   IF translateArcLogSeqRange%ISOPEN THEN
      CLOSE translateArcLogSeqRange;
   END IF;
   IF translateArcLogSeqRange2%ISOPEN THEN
      CLOSE translateArcLogSeqRange2;
   END IF;
   IF translateArcLogTimeRange%ISOPEN THEN
      CLOSE translateArcLogTimeRange;
   END IF;
   IF translateArcLogSCNRange%ISOPEN THEN
      CLOSE translateArcLogSCNRange;
   END IF;
   IF translateArcLogSCNRange2%ISOPEN THEN
      CLOSE translateArcLogSCNRange2;
   END IF;
   IF translateArcLogPattern%ISOPEN THEN
      CLOSE translateArcLogPattern;
   END IF;
   IF lbal2%ISOPEN THEN
      CLOSE lbal2;
   END IF;
   IF ldbi%ISOPEN THEN
      CLOSE ldbi;
   END IF;
   IF lrtbs%ISOPEN THEN
      CLOSE lrtbs;
   END IF;
   IF getOfflineRangeCopy_c%ISOPEN THEN
      CLOSE getOfflineRangeCopy_c;
   END IF;
   IF rddf%ISOPEN THEN
      CLOSE rddf;
   END IF;
   IF bmrAddCorruptTable_c%ISOPEN THEN
      CLOSE bmrAddCorruptTable_c;
   END IF;
   IF findBackupsetFiles%ISOPEN THEN
      CLOSE findBackupsetFiles;
   END IF;
   IF findAllBackupPiece%ISOPEN THEN
      CLOSE findAllBackupPiece;
   END IF;
   IF dfBackupHistory_c%ISOPEN THEN
      CLOSE dfBackupHistory_c;
   END IF;
   IF alBackupHistory_c%ISOPEN THEN
      CLOSE alBackupHistory_c;
   END IF;
   IF bsBackupHistory_c%ISOPEN THEN
      CLOSE bsBackupHistory_c;
   END IF;
   IF inCorebsRec_c%ISOPEN THEN
      CLOSE inCorebsRec_c;
   END IF;
   validateBackupSet_method := NULL;
END resetAll;
---------------------------
-- Backup Set Validation --
---------------------------
------------------------------ findValidBackupSet -----------------------------
PROCEDURE findValidBackupSet(
   backupSetRec            IN     rcvRec_t
  ,deviceType              IN     varchar2       DEFAULT NULL
  ,tag                     IN     varchar2       DEFAULT NULL
  ,available               IN     number         DEFAULT TRUE#  -- for compat.
  ,unavailable             IN     number         DEFAULT FALSE# -- for compat.
  ,deleted                 IN     number         DEFAULT FALSE# -- for compat.
  ,expired                 IN     number         DEFAULT FALSE# -- for compat.
  ,availableMask           IN     binary_integer DEFAULT NULL)  -- for compat.
IS
BEGIN
   deb(DEB_ENTER, 'findValidBackupSet');
   findValidBackupSet(bsKey         => backupSetRec.bsKey_con,
                      pieceCount    => backupSetRec.pieceCount_con,
                      deviceType    => deviceType,
                      tag           => tag,
                      availableMask => NVL(availableMask,
                          computeAvailableMask(available, unavailable, deleted,
                                               expired)));
   deb(DEB_EXIT);
END findValidBackupSet;
-- This version of findValidBackupSet takes a bsRec_t instead of a rcvRec_t.
------------------------------ findValidBackupSet -----------------------------
PROCEDURE findValidBackupSet(
   backupSetRec            IN     bsRec_t
  ,deviceType              IN     varchar2       DEFAULT NULL
  ,tag                     IN     varchar2       DEFAULT NULL
  ,available               IN     number         DEFAULT TRUE#  -- for compat.
  ,unavailable             IN     number         DEFAULT FALSE# -- for compat.
  ,deleted                 IN     number         DEFAULT FALSE# -- for compat.
  ,expired                 IN     number         DEFAULT FALSE# -- for compat.
  ,availableMask           IN     binary_integer DEFAULT NULL)  -- for compat.
IS
BEGIN
   deb(DEB_ENTER, 'findValidBackupSet bsRec_t');
   findValidBackupSet(bsKey         => backupSetRec.key,
                      pieceCount    => backupSetRec.pieceCount,
                      deviceType    => deviceType,
                      tag           => tag,
                      availableMask => NVL(availableMask,
                          computeAvailableMask(available, unavailable, deleted,
                                               expired)));
   deb(DEB_EXIT);
END findValidBackupSet;
------------------------------ getValidBackupSet ------------------------------
FUNCTION getValidBackupSet(
   validBackupSetRec            OUT validBackupSetRec_t
  ,checkDeviceIsAllocated       IN  number DEFAULT FALSE#)
RETURN number IS
   lastCode     number;
   checkRc      number;
   local        validBackupSetRec_t;
BEGIN
   deb(DEB_ENTER, 'getValidBackupSet');
   -- If the cursor is not open, just return FALSE#.
   IF (getValidBackupSetCursor = 'findValidBackupSet1P_c') THEN
      IF (NOT findValidBackupSet1P_c%ISOPEN) THEN
         RETURN FALSE#;
      END IF;
   ELSIF (getValidBackupSetCursor = 'findValidBackupSet_c') THEN
      IF (NOT findValidBackupSet_c%ISOPEN) THEN
         RETURN FALSE#;
      END IF;
   ELSE
      raise_application_error(-20204, 'Translation not started');
   END IF;
<<nextRow>>
   IF (getValidBackupSetCursor = 'findValidBackupSet1P_c') THEN
      FETCH findValidBackupSet1P_c
         INTO local;
      IF (findValidBackupSet1P_c%NOTFOUND) THEN
         CLOSE findValidBackupSet1P_c;
         deb(DEB_EXIT, 'with: FALSE#');
         RETURN FALSE#;
      END IF;
   ELSIF (getValidBackupSetCursor = 'findValidBackupSet_c') THEN
      FETCH findValidBackupSet_c
         INTO local;
      IF (findValidBackupSet_c%NOTFOUND) THEN
         CLOSE findValidBackupSet_c;
         deb(DEB_EXIT, 'with: FALSE#');
         RETURN FALSE#;
      END IF;
   END IF;
   lastCode := getValidBackupSetLast.code;      -- save for test below
   getValidBackupSetLast := local;              -- save for next time here
   IF (local.code <= lastCode) THEN
      -- The findValidBackupSet cursor returns 4 colums: deviceType, tag,
      -- copy#, and a code (1,2,3).  If the code is 1, it means we found a
      -- complete set of pieces with the same deviceType, tag, and copy#.  We
      -- always want to process records of type 1.  If the code is 2, it means
      -- we ignored copy#, and found a complete set of pieces with the same
      -- deviceType and tag.  We only want to process records of type 2 if
      -- we did not see this deviceType/tag combination with code 1.
      -- A code 3 record means we ignored copy# and tag, and found a complete
      -- set of pieces with the same deviceType.  We only want to process
      -- records of code 3 if we did not see any records of type 1 or 2
      -- for this device type.
      -- The order by allows us to implement this very easily.  We return a
      -- record only if its code is <= the code for the last record we
      -- fetched.  This works because if there is a code 2 record, then it
      -- will be followed by a code 3 record.  If there is a code 1 record, it
      -- will be followed by a code 2 and then code 3 record.
      -- Since this record's code is <= the previous record's code, we
      -- must be looking at a different deviceType, tag, and/or copy# than
      -- before, or this is the first record.  In either case, we want to
      -- process the record.
      IF (checkDeviceIsAllocated = TRUE#) THEN
         IF (isDeviceTypeAllocated(local.deviceType) = FALSE#) THEN
            deb(DEB_IN, 'device type not allocated: ' ||
                local.deviceType);
            GOTO nextRow;
         END IF;
      END IF;
      validBackupSetRec := local;               -- set OUT mode arg
      deb(DEB_IN, 'returning valid rec deviceType=' ||
          local.deviceType || ' tag=' || local.tag || ' copyNumber=' ||
          to_char(local.copyNumber));
      deb(DEB_EXIT, 'with: TRUE#');
      RETURN TRUE#;
   ELSE
      deb(DEB_IN, ' local.code=' || to_char(local.code) ||
          ' lastCode=' || to_char(lastCode));
      GOTO nextRow;
   END IF;
   deb(DEB_EXIT);
END getValidBackupSet;
---------------------
-- Get an rcvRec_t --
---------------------
---------------------------------- getRcvRec ----------------------------------
FUNCTION getRcvRec(
   funCode      IN number
  ,rcvRec       OUT rcvRec_t
  ,callAgain    OUT number)
RETURN number IS
   rc           number;
BEGIN
   deb(DEB_ENTER, 'getRcvRec');
   rc := 0;                                     -- init for procedures
   callAgain := TRUE#;
   deb(DEB_IN, ' funCode=' || to_char(funCode));
   IF (funCode = getCfCopy) THEN
      getControlfileCopy(rcvRec);
   ELSIF (funCode = getDfCopy) THEN
      getDatafileCopy(rcvRec);
   ELSIF (funCode = getAnyProxy) THEN
      getProxyCopy(rcvRec);
   ELSIF (funCode = getCfBackup) THEN
      rc := getControlfileBackup(rcvRec);
      callAgain := FALSE#;
   ELSIF (funCode = getSfBackup) THEN
      rc := getSpfileBackup(rcvRec);
      callAgain := FALSE#;
   ELSIF (funCode = listCfCopy) THEN
      listGetControlfileCopy(rcvRec);
   ELSIF (funCode = listDfCopy) THEN
      listGetDatafileCopy(rcvRec);
   ELSIF (funCode = listCfBackup) THEN
      listGetControlfileBackup(rcvRec);
   ELSIF (funCode = listSfBackup) THEN
      listGetSpfileBackup(rcvRec);
   ELSIF (funCode = listDfBackup) THEN
      listGetDatafileBackup(rcvRec);
   ELSIF (funCode = listAlBackup) THEN
      listGetArchivedLogBackup(rcvRec);
   ELSIF (funCode = listDfProxy) THEN
      listGetProxyDatafile(rcvRec);
   ELSIF (funCode = getRecovAction) THEN
      callAgain := getRecoveryAction(rcvRec);
   ELSIF (funCode = getAlBackup) THEN
      rc := getArchivedLogBackup(rcvRec);
      callAgain := FALSE#;
   ELSIF (funCode = listAlCopy) THEN
      listGetArchivedLogCopy(rcvRec);
   ELSIF (funCode = listBSet) THEN
      listGetBackupsetFiles(rcvRec);
   ELSIF (funCode = getAllBSet) THEN
      getAllBackupSet(rcvRec);
   ELSE
      deb(DEB_EXIT, 'with error 20999');
      raise_application_error(-20999, 'getRcvRec: unknown funCode: ' ||
         to_char(funCode));
   END IF;
   printRcvRec(rcvRec);
   deb(DEB_EXIT, 'with rc:'||TO_CHAR(rc));
   RETURN rc;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
END getRcvRec;
--------------------------
-- Datafile Translation --
--------------------------
------------------------------ translateDatabase ------------------------------
PROCEDURE translateDatabase(
   sinceUntilSCN IN number DEFAULT NULL)
IS
   fromSCN      number;
   toSCN        number;
BEGIN
   deb(DEB_ENTER, 'translateDatabase');
   validateState(getDatafileCursor);
   IF (untilSCN is NULL) THEN
      -- This range means:  all datafiles that exist now
      fromSCN := MAXSCNVAL;
      toSCN   := MAXSCNVAL;
   ELSE                                 -- an until clause is in effect
      fromSCN := untilSCN;
      IF (sinceUntilSCN = TRUE#) THEN
         -- This flag means the caller wants datafiles that existed
         -- since the until SCN.  So the translation range is:
         -- untilSCN...MAXSCNVAL
         toSCN := MAXSCNVAL;
      ELSE
         -- This is the normal case when an until clause is in effect.
         -- We want the datafiles that existed at the until SCN, but not
         -- any that were created after that.
         toSCN := fromSCN;
      END IF;
   END IF;
   deb(DEB_OPEN, 'translateDatabase_c');
   OPEN translateDatabase_c(fromSCN, toSCN);
   getDatafileCursor       := 'translateDatabase';
   getDatafileNoRows.error := NULL;             -- error not possible
   skipTablespaceCount     := 0;
   getDatafileLast.dfNumber := NULL;            -- no last row yet
   deb(DEB_EXIT);
END translateDatabase;
-- Public procedure to add a tablespace to the skip list.
-------------------------------- skipTableSpace -------------------------------
PROCEDURE skipTableSpace(
   ts_name IN varchar2)
IS
BEGIN
   skipTablespaceCount := skipTablespaceCount + 1;
   skipTablespaceList(skipTablespaceCount) := ts_name;
END skipTableSpace;
----------------------------- translateTablespace -----------------------------
PROCEDURE translateTablespace(
   ts_name IN varchar2)
IS
BEGIN
   deb(DEB_ENTER, 'translateTablespace');
   validateState(getDatafileCursor);
   deb(DEB_OPEN, 'translateTablespace_c');
   OPEN translateTablespace_c(tsName => ts_name);
   getDatafileCursor       := 'translateTablespace';
   getDatafileNoRows.error := -20202;
   getDatafileNoRows.msg   := 'Tablespace does not exist';
   skipTablespaceCount     := 0;
   getDatafileLast.dfNumber := NULL;            -- no last row yet
   deb(DEB_EXIT);
END translateTablespace;
------------------------------ translateDataFile ------------------------------
PROCEDURE translateDataFile(
   fname IN varchar2)
IS
BEGIN
   deb(DEB_ENTER, 'translateDataFile_1');
   validateState(getDatafileCursor);
   deb(DEB_OPEN, 'translateDatafileName');
   OPEN translateDatafileName(fileName => fname);
   IF (untilSCN is NULL and untilTime is NULL) THEN
      getDatafileNoRows.error := -20201;
      getDatafileNoRows.msg   := 'Datafile does not exist';
   ELSE
      getDatafileNoRows.error := -20222;
      getDatafileNoRows.msg   :=
         'Datafile name does not exist or is ambiguous';
   END IF;
   getDatafileCursor   := 'translateDatafileName';
   skipTablespaceCount := 0;
   getDatafileLast.dfNumber := NULL;            -- no last row yet
   deb(DEB_EXIT);
END translateDatafile;
------------------------------ translateDataFile ------------------------------
PROCEDURE translateDataFile(
   fno IN number)
IS
BEGIN
   deb(DEB_ENTER, 'translateDataFile_2');
   validateState(getDatafileCursor);
   deb(DEB_OPEN, 'translateDatafileNumber');
   OPEN translateDatafileNumber(fno => fno);
   getDatafileCursor       := 'translateDatafileNumber';
   getDatafileNoRows.error :=  -20201;
   getDatafileNoRows.msg   := 'Datafile does not exist';
   skipTablespaceCount     := 0;
   getDatafileLast.dfNumber := NULL;            -- no last row yet
   deb(DEB_EXIT);
END translateDatafile;
------------------------------ translateDataFile ------------------------------
PROCEDURE translateDataFile(
   fno    IN number
  ,ckpscn IN number)
IS
BEGIN
   deb(DEB_ENTER, 'translateDataFile_3');
   validateState(getDatafileCursor);
   deb(DEB_OPEN, 'translateDatafileCheckpoint');
   OPEN translateDatafileCheckpoint(fno    => fno,
                                    ckpSCN => ckpscn);
   getDatafileCursor       := 'translateDatafileCheckpoint';
   getDatafileNoRows.error :=  -20201;
   getDatafileNoRows.msg   := 'Datafile does not exist';
   skipTablespaceCount     := 0;
   getDatafileLast.dfNumber := NULL;            -- no last row yet
   deb(DEB_EXIT);
END translateDatafile;
----------------------------- translateAllDataFile ----------------------------
PROCEDURE translateAllDatafile
IS
BEGIN
   deb(DEB_ENTER, 'translateAllDataFile');
   IF (translateAllDatafile_c%ISOPEN) THEN
      CLOSE translateAllDatafile_c;
   END IF;
   deb(DEB_OPEN, 'translateAllDatafile_c');
   OPEN translateAllDatafile_c;
   getDatafileCursor       := 'translateAllDatafile';
   getDatafileNoRows.error := NULL;             -- error not possible
   skipTablespaceCount     := 0;
   getDatafileLast.dfNumber := NULL;            -- no last row yet
   deb(DEB_EXIT);
END;
PROCEDURE translateCorruptList
IS
BEGIN
   validateState(getDatafileCursor);
   OPEN translateCorruptList_c;
   getDatafileCursor       := 'translateCorruptList';
   getDatafileNoRows.error :=  -20504;
   getDatafileNoRows.msg   := 'Corruption List does not exist';
   skipTablespaceCount     := 0;
   getDatafileLast.dfNumber := NULL;            -- no last row yet
END translateCorruptList;
-- Main getDatafile routine
--------------------------------- getDatafile ---------------------------------
PROCEDURE getDatafile(
   dfRec     OUT dfRec_t
  ,oldClient IN  boolean DEFAULT FALSE)
IS
   getDatafileRowcount  number;
   local                dfRec_t;
BEGIN
   deb(DEB_ENTER, 'getDataFile_1');
<<nextRow>>
   IF (getDatafileCursor = 'translateDatabase') THEN
      FETCH translateDatabase_c
       INTO local;
      IF (translateDatabase_c%NOTFOUND) THEN
         -- Save rowcount before closing cursor
         getDatafileRowcount := translateDatabase_c%ROWCOUNT;
         CLOSE translateDatabase_c;
      END IF;
   ELSIF (getDatafileCursor = 'translateAllDatafile') THEN
      FETCH translateAllDatafile_c
       INTO local;
      IF (translateAllDatafile_c%NOTFOUND) THEN
         -- Save rowcount before closing cursor
         getDatafileRowcount := translateAllDatafile_c%ROWCOUNT;
         CLOSE translateAllDatafile_c;
      END IF;
   ELSIF (getDatafileCursor = 'translateTablespace') THEN
      FETCH translateTablespace_c
       INTO local;
      IF (translateTablespace_c%NOTFOUND) THEN
         -- Save rowcount before closing cursor
         getDatafileRowcount := translateTablespace_c%ROWCOUNT;
         CLOSE translateTablespace_c;
      END IF;
   ELSIF (getDatafileCursor = 'translateDatafileName') THEN
      FETCH translateDatafileName
       INTO local;
      IF (translateDatafileName%NOTFOUND) THEN
         -- Save rowcount before closing cursor
         getDatafileRowcount := translateDatafileName%ROWCOUNT;
         CLOSE translateDatafileName;
      END IF;
      IF (oldClient) THEN
         -- We won't be called again, so close the cursor now.
         IF (translateDatafileName%ISOPEN) THEN
            CLOSE translateDatafileName;
         END IF;
         getDatafileCursor := NULL;
      END IF;
   ELSIF (getDatafileCursor = 'translateDatafileNumber') THEN
      FETCH translateDatafileNumber
       INTO local;
      IF (translateDatafileNumber%NOTFOUND) THEN
         -- Save rowcount before closing cursor
         getDatafileRowcount := translateDatafileNumber%ROWCOUNT;
         CLOSE translateDatafileNumber;
      END IF;
      IF (oldClient) THEN
         -- We won't be called again, so close the cursor now.
         IF (translateDatafileNumber%ISOPEN) THEN
            CLOSE translateDatafileNumber;
         END IF;
         getDatafileCursor := NULL;
      END IF;
   ELSIF (getDatafileCursor = 'translateDatafileCheckpoint') THEN
      FETCH translateDatafileCheckpoint
       INTO local;
      IF (translateDatafileCheckpoint%NOTFOUND) THEN
         -- Save rowcount before closing cursor
         getDatafileRowcount := translateDatafileCheckpoint%ROWCOUNT;
         CLOSE translateDatafileCheckpoint;
      END IF;
      IF (oldClient) THEN
         -- We won't be called again, so close the cursor now.
         IF (translateDatafileCheckpoint%ISOPEN) THEN
            CLOSE translateDatafileCheckpoint;
         END IF;
         getDatafileCursor := NULL;
      END IF;
   ELSIF (getDatafileCursor = 'translateCorruptList') THEN
      FETCH translateCorruptList_c
       INTO local;
      IF (translateCorruptList_c%NOTFOUND) THEN
         -- Save rowcount before closing cursor
         getDatafileRowcount := translateCorruptList_c%ROWCOUNT;
         CLOSE translateCorruptList_c;
      END IF;
   ELSE
      deb(DEB_EXIT, 'with error 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
   IF (getDatafileRowcount IS NOT NULL) THEN    -- if %NOTFOUND
      getDatafileCursor := NULL;                -- we closed it above
      IF (getDatafileRowcount = 0 AND
          getDatafileNoRows.error IS NOT NULL) THEN
         -- Signal the appropriate error.
         deb(DEB_EXIT, 'with norows error');
         raise_application_error(getDatafileNoRows.error,
                                 getDatafileNoRows.msg);
      ELSE
         deb(DEB_EXIT, 'with no more records');
         RAISE no_data_found;                   -- signal end-of-fetch
      END IF;
   END IF;
   IF (skipTablespace(local.tsName)) THEN
      GOTO nextRow;
   END IF;
   -- This isn't needed right now, but I am leaving it in because
   -- it can't hurt.
   IF (getDatafileLast.dfNumber = local.dfNumber AND
       getDatafileLast.dfCreationSCN = local.dfCreationSCN) THEN
      GOTO nextRow;
   END IF;
   getDatafileLast := local;
   dfRec := local;                              -- set OUT mode arg
   deb(DEB_EXIT);
END getDatafile;
-- Public procedure for 8.1.x and prior releases.
--------------------------------- getDatafile ---------------------------------
PROCEDURE getDatafile(
   file#                        OUT number
  ,crescn                       OUT number
  ,creation_time                OUT date
  ,fname                        OUT varchar2
  ,ts_name                      OUT varchar2
  ,status                       OUT number
  ,blksize                      OUT number
  ,kbytes                       OUT number
  ,blocks                       OUT number
  ,unrecoverable_change#        OUT number
  ,stop_change#                 OUT number
  ,read_only                    OUT number)
IS
   dfRec        dfRec_t;
BEGIN
   deb(DEB_ENTER, 'getDataFile_2');
   getDatafile(dfRec, oldClient => TRUE);
   file#                 := dfRec.dfNumber;
   crescn                := dfRec.dfCreationSCN;
   creation_time         := dfRec.dfCreationTime;
   fname                 := dfRec.fileName;
   ts_name               := dfRec.tsName;
   status                := 0; -- this is kccfesta, which we don't have
   blksize               := dfRec.blockSize;
   kbytes                := dfRec.kbytes;
   blocks                := dfRec.blocks;
   unrecoverable_change# := 0; -- this is kccfeurs which isn't kept in rcvcat
   stop_change#          := dfRec.stopSCN;
   read_only             := dfRec.readOnly;
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      -- This is end-of-fetch.
      file# := NULL;
   deb(DEB_EXIT, 'with no more records');
END getDatafile;
----------------------------
-- Online Log Translation --
----------------------------
----------------------------- translateOnlineLogs -----------------------------
PROCEDURE translateOnlineLogs
IS
BEGIN
   deb(DEB_ENTER, 'translateOnlineLogs');
   IF (translateOnlineLogs_c%ISOPEN) THEN
      validateState('you bozo');                -- raise the error
   END IF;
   deb(DEB_OPEN, 'translateOnlineLogs_c');
   OPEN translateOnlineLogs_c;
   deb(DEB_EXIT);
END translateOnlineLogs;
--------------------------------- getOnlineLog --------------------------------
PROCEDURE getOnlineLog(
   fname        OUT varchar2
  ,thread#      OUT number
  ,group#       OUT number)
IS
BEGIN
   deb(DEB_ENTER, 'getOnlineLog');
   FETCH translateOnlineLogs_c
    INTO thread#, group#, fname;
   IF (translateOnlineLogs_c%NOTFOUND) THEN
      CLOSE translateOnlineLogs_c;
      deb(DEB_EXIT, 'with NULL (no archivelog found)'||fname);
      fname := NULL;                            -- indicate end-of-fetch
      RETURN;
   END IF;
   deb(DEB_EXIT, 'with archivelog:'||fname);
END getOnlineLog;
------------------------------
-- Archived Log Translation --
------------------------------
-------------------------------- getArchivedLog -------------------------------
PROCEDURE getArchivedLog(
   alRec       OUT alRec_t,
   closeCursor IN  boolean DEFAULT FALSE)
IS
   getArchivedLogRowcount       number;
   local                        alRec_t;
BEGIN
   deb(DEB_ENTER, 'getArchivedLog');
<<nextRow>>
   IF (getArchivedLogCursor = 'translateArcLogKey') THEN
      FETCH translateArcLogKey
       INTO local;
      IF (translateArcLogKey%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogKey%ROWCOUNT;
         CLOSE translateArcLogKey;
      END IF;
      IF (closeCursor AND translateArcLogKey%ISOPEN) THEN
         CLOSE translateArcLogKey;
      END IF;
   ELSIF (getArchivedLogCursor = 'translateArcLogName') THEN
      FETCH translateArcLogName
       INTO local;
      IF (translateArcLogName%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogName%ROWCOUNT;
         CLOSE translateArcLogName;
      END IF;
      IF (closeCursor AND translateArcLogName%ISOPEN) THEN
         CLOSE translateArcLogName;
      END IF;
   ELSIF (getArchivedLogCursor = 'translateArcLogSeqRange') THEN
      FETCH translateArcLogSeqRange
       INTO local;
      IF (translateArcLogSeqRange%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogSeqRange%ROWCOUNT;
         CLOSE translateArcLogSeqRange;
      END IF;
      IF (closeCursor AND translateArcLogSeqRange%ISOPEN) THEN
         CLOSE translateArcLogSeqRange;
      END IF;
   ELSIF (getArchivedLogCursor = 'translateArcLogSeqRange2') THEN
      FETCH translateArcLogSeqRange2
       INTO local;
      IF (translateArcLogSeqRange2%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogSeqRange2%ROWCOUNT;
         CLOSE translateArcLogSeqRange2;
      END IF;
      IF (closeCursor AND translateArcLogSeqRange2%ISOPEN) THEN
         CLOSE translateArcLogSeqRange2;
      END IF;
   ELSIF (getArchivedLogCursor = 'translateArcLogTimeRange') THEN
      FETCH translateArcLogTimeRange
       INTO local;
      IF (translateArcLogTimeRange%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogTimeRange%ROWCOUNT;
         CLOSE translateArcLogTimeRange;
      END IF;
      IF (closeCursor AND translateArcLogTimeRange%ISOPEN) THEN
         CLOSE translateArcLogTimeRange;
      END IF;
   ELSIF (getArchivedLogCursor = 'translateArcLogTimeRange2') THEN
      FETCH translateArcLogTimeRange2
       INTO local;
      IF (translateArcLogTimeRange2%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogTimeRange2%ROWCOUNT;
         CLOSE translateArcLogTimeRange2;
      END IF;
      IF (closeCursor AND translateArcLogTimeRange2%ISOPEN) THEN
         CLOSE translateArcLogTimeRange2;
      END IF;
   ELSIF (getArchivedLogCursor = 'translateArcLogSCNRange') THEN
      FETCH translateArcLogSCNRange
       INTO local;
      IF (translateArcLogSCNRange%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogSCNRange%ROWCOUNT;
         CLOSE translateArcLogSCNRange;
      END IF;
      IF (closeCursor AND translateArcLogSCNRange%ISOPEN) THEN
         CLOSE translateArcLogSCNRange;
      END IF;
   ELSIF (getArchivedLogCursor = 'translateArcLogSCNRange2') THEN
      FETCH translateArcLogSCNRange2
       INTO local;
      IF (translateArcLogSCNRange2%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogSCNRange2%ROWCOUNT;
         CLOSE translateArcLogSCNRange2;
      END IF;
      IF (closeCursor AND translateArcLogSCNRange2%ISOPEN) THEN
         CLOSE translateArcLogSCNRange2;
      END IF;
   ELSIF (getArchivedLogCursor = 'translateArcLogPattern') THEN
      FETCH translateArcLogPattern
       INTO local;
      IF (translateArcLogPattern%NOTFOUND) THEN
         getArchivedLogRowcount := translateArcLogPattern%ROWCOUNT;
         CLOSE translateArcLogPattern;
      END IF;
      IF (closeCursor AND translateArcLogPattern%ISOPEN) THEN
         CLOSE translateArcLogPattern;
      END IF;
   ELSE
      deb(DEB_EXIT, 'with error 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
   IF (closeCursor) THEN
      getArchivedLogCursor := NULL;
   END IF;
   IF (getArchivedLogRowcount IS NOT NULL) THEN
      getArchivedLogCursor := NULL;             -- we closed it above
      getArchivedLogLast   := NULL;             -- clear for next time
      IF (getArchivedLogRowcount = 0 AND
          getArchivedLogNoRows.error IS NOT NULL) THEN
         -- Signal the appropriate error.
         deb(DEB_EXIT, 'with norows error');
         raise_application_error(getArchivedLogNoRows.error,
                                 getArchivedLogNoRows.msg);
      ELSE
         deb(DEB_EXIT, 'with no more records');
         RAISE no_data_found;                   -- signal end-of-fetch
      END IF;
   END IF;
  -- Eliminate duplicate archived logs unless getArchivedLogDuplicates is true
   IF (local.thread   = getArchivedLogLast.thread AND
       local.sequence = getArchivedLogLast.sequence AND
       local.lowSCN   = getArchivedLogLast.lowSCN) THEN
     local.duplicate := TRUE#;
   END IF;
   IF (getArchivedLogDuplicates = FALSE# AND    -- if don't want duplicates
       local.duplicate = TRUE#) THEN
      GOTO nextRow;
   END IF;
   -- If stamp is -1, then this came from the brl table.  Change stamp to
   -- be null since -1 is not a legal stamp value.
   IF (local.stamp = -1) THEN
      local.stamp := NULL;
   END IF;
   IF getArchivedLogCursor IS NULL THEN
      getArchivedLogLast := NULL;               -- clear for next time
      deb(DEB_PRINT, 'getArchivedLogLast := NULL');
   ELSE
      getArchivedLogLast := local;
      deb(DEB_PRINT, 'getArchivedLogLast := local');
   END IF;
   alRec := local;                              -- set OUT mode arg
   deb(DEB_EXIT);
END getArchivedLog;
--------------------------- translateArchivedLogKey ---------------------------
PROCEDURE translateArchivedLogKey(
   alKey        IN number
  ,needstby     IN number DEFAULT NULL)
IS
BEGIN
   deb(DEB_ENTER, 'translateArchivedLogKey');
   validateState(getArchivedLogCursor);
   deb(DEB_OPEN, 'translateArcLogKey');
   OPEN translateArcLogKey(alKey => alKey, needstby => needstby);
   getArchivedLogCursor       := 'translateArcLogKey';
   getArchivedLogDuplicates   := NULL;
   getArchivedLogNoRows.error := -20240;
   getArchivedLogNoRows.msg   := 'Archived log does not exist';
   deb(DEB_EXIT);
END translateArchivedLogKey;
--------------------------- translateArchivedLogKey ---------------------------
PROCEDURE translateArchivedLogKey(
   al_key       IN  number
  ,available    IN  number DEFAULT 1     -- ignored (for compatability)
  ,unavailable  IN  number DEFAULT 1     -- ignored (for compatability)
  ,deleted      IN  number DEFAULT 1     -- ignored (for compatability)
  ,online       IN  number DEFAULT 1     -- ignored (for compatability)
  ,recid        OUT number
  ,stamp        OUT number
  ,thread#      OUT number
  ,sequence#    OUT number
  ,low_scn      OUT number
  ,reset_scn    OUT number
  ,block_size   OUT number
  ,fname        OUT varchar2
  ,needstby     IN number DEFAULT NULL)
IS
   alRec        alRec_t;
BEGIN
   deb(DEB_ENTER, 'translateArchivedLogKey816');
   translateArchivedLogKey(alKey => al_key, needstby => needstby);
   getArchivedLog(alRec       => alRec,
                  closeCursor => TRUE);
   recid        := alRec.recid;
   stamp        := alRec.stamp;
   thread#      := alRec.thread;
   sequence#    := alRec.sequence;
   low_scn      := alRec.lowSCN;
   reset_scn    := alRec.rlgSCN;
   block_size   := alRec.blockSize;
   fname        := alRec.fileName;
   deb(DEB_EXIT);
END translateArchivedLogKey;
-- Translate archived log name.  The archived logs are ordered by
-- stamp in order to return most recently created log first, because it
-- most likely to exist.  Note that archived logs that belong to any
-- incarnation of the current database are returned.
--------------------------- translateArchivedLogName --------------------------
PROCEDURE translateArchivedLogName(
   fname        IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number                        -- ignored
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL)
IS
BEGIN
   deb(DEB_ENTER, 'translateArchivedLogName');
   validateState(getArchivedLogCursor);
   deb(DEB_OPEN, 'translateArcLogName');
   OPEN translateArcLogName(fname       => fname,
                            online      => online,
                            statusMask  => NVL(statusMask,
                                   computeAvailableMask(available, unavailable,
                                                        deleted, 0)),
                            needstby    => needstby);
   getARchivedLogCursor       := 'translateArcLogName';
   getArchivedLogDuplicates   := duplicates;
   getArchivedLogNoRows.error := -20240;
   getArchivedLogNoRows.msg   := 'Archived log does not exist';
   deb(DEB_EXIT);
END translateArchivedLogName;
-- Translate an archived log sequence range.  The archived logs are ordered
-- by thread#, first_change#, sequence# to make detection of "missing"
-- archived logs in the range easy and to return the logs in the order that
-- recovery will apply them.  Note that sequence number is reset if the
-- controlfile is recreated so first change must be before sequence# number
-- in the order by clause.
------------------------- translateArchivedLogSeqRange ------------------------
PROCEDURE translateArchivedLogSeqRange(
   thread#      IN number
  ,fromseq#     IN number
  ,toseq#       IN number
  ,pattern      IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number                        -- ignored
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL)
IS
   mask number := NVL(statusMask,
                     computeAvailableMask(available, unavailable, deleted, 0));
BEGIN
   deb(DEB_ENTER, 'translateArchivedLogSeqRange');
   validateState(getArchivedLogCursor);
   IF (thread# is NULL) THEN
      deb(DEB_EXIT, 'with error 20210');
      raise_application_error(-20210, 'Thread# is missing');
   END IF;
   IF (bitand(mask,BSdeleted) != 0 AND pattern IS NULL) THEN
      -- Use the cursor that also looks at backup redo logs.
      -- The online parameter is assumed to be FALSE#.  Available and
      -- unavailable are ignored.  Since we are looking at backup redo logs,
      -- pattern cannot be implemented here, so we use this cursor only if
      -- pattern is null.
      deb(DEB_OPEN, 'translateArcLogSeqRange2');
      OPEN translateArcLogSeqRange2(thread#     => thread#,
                                    fromseq#    => fromseq#,
                                    toseq#      => toseq#,
                                    needstby    => needstby);
      getArchivedLogCursor       := 'translateArcLogSeqRange2';
   ELSE
      deb(DEB_OPEN, 'translateArcLogSeqRange');
      OPEN translateArcLogSeqRange(thread#     => thread#,
                                   fromseq#    => fromseq#,
                                   toseq#      => toseq#,
                                   pattern     => pattern,
                                   statusMask  => mask,
                                   online      => online,
                                   needstby    => needstby);
      getArchivedLogCursor       := 'translateArcLogSeqRange';
   END IF;
   getArchivedLogDuplicates   := duplicates;
   getArchivedLogNoRows.error := -20242;
   getArchivedLogNoRows.msg   := 'No archived logs in the range specified';
   setTransClause(thread     => thread#,
                  fromSeq    => fromseq#,
                  toSeq      => toseq#,
                  pattern    => pattern);
   deb(DEB_EXIT);
END translateArchivedLogSeqRange;
-- Translate an archived log time range
------------------------ translateArchivedLogTimeRange ------------------------
PROCEDURE translateArchivedLogTimeRange(
   thread#      IN number
  ,fromTime     IN date
  ,toTime       IN date
  ,pattern      IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number                        -- ignored
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number DEFAULT NULL)
IS
   mask number := NVL(statusMask,
                     computeAvailableMask(available, unavailable, deleted, 0));
BEGIN
   deb(DEB_ENTER, 'translateArchivedLogTimeRange');
   validateState(getArchivedLogCursor);
   IF (bitand(mask,BSdeleted) != 0 AND pattern IS NULL) THEN
      -- Use the cursor that also looks at backup redo logs.
      -- The online parameter is assumed to be FALSE#.  Available and
      -- unavailable are ignored.  Since we are looking at backup redo logs,
      -- pattern cannot be implemented here, so we use this cursor only if
      -- pattern is null.
      deb(DEB_OPEN, 'translateArcLogTimeRange2');
      OPEN translateArcLogTimeRange2(thread#     => thread#,
                                     fromTime    => fromTime,
                                     toTime      => toTime,
                                     needstby    => needstby);
      getArchivedLogCursor       := 'translateArcLogTimeRange2';
   ELSE
      deb(DEB_OPEN, 'translateArcLogTimeRange');
      OPEN translateArcLogTimeRange(thread#     => thread#,
                                    fromTime    => fromTime,
                                    toTime      => toTime,
                                    pattern     => pattern,
                                    statusMask  => mask,
                                    online      => online,
                                    needstby    => needstby);
      getArchivedLogCursor       := 'translateArcLogTimeRange';
   END IF;
   getArchivedLogDuplicates   := duplicates;
   getArchivedLogNoRows.error := -20242;
   getArchivedLogNoRows.msg   := 'No archived logs in the range specified';
   setTransClause(thread   => thread#,
                  fromTime => fromTime,
                  toTime   => toTime,
                  pattern  => pattern);
   deb(DEB_EXIT);
END translateArchivedLogTimeRange;
-- Translate an archived log scn range
------------------------- translateArchivedLogSCNRange ------------------------
PROCEDURE translateArchivedLogSCNRange(
   thread#      IN number
  ,fromSCN      IN number
  ,toSCN        IN number
  ,pattern      IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL)
IS
   adjusted_toSCN number;
   mask           number := NVL(statusMask,
                     computeAvailableMask(available, unavailable, deleted, 0));
BEGIN
   deb(DEB_ENTER, 'translateArchivedLogSCNRange');
   validateState(getArchivedLogCursor);
   IF (untilTime IS NULL) THEN
      -- Adjust the toSCN to take the until SCN into account.  The untilSCN
      -- was either specified directly by the user, or it was computed from
      -- the until logseq.  In either case, it is the exact SCN at which
      -- recovery will stop.
      adjusted_toSCN := least(toSCN, nvl(untilSCN, toSCN));
   ELSE
      -- Leave the toSCN alone.  We cannot adjust the toSCN using
      -- the untilSCN here because the until SCN was estimated by
      -- computeUntilSCN(), and this procedure deliberately estimates the
      -- SCN low.  We cannot tolerate a low estimated SCN here because
      -- then we might filter out a log that will be needed by recovery.
      -- So instead, we pass the untilTime to the cursor.
      adjusted_toSCN := toSCN;
   END IF;
   -- 8.1.6 and later always make sure that the toSCN is greater than the
   -- fromSCN, but 8.1.5 and earlier will call us with fromSCN==toSCN.
   -- The query will fail if they are equal, so make the toSCN greater than
   -- the fromSCN.  It is also possible that adjusting by the untilSCN above
   -- made the fromSCN==toSCN.
   IF (adjusted_toSCN <= fromSCN) THEN
      adjusted_toSCN := fromSCN+1;
   END IF;
   IF (bitand(mask,BSdeleted) != 0 AND pattern IS NULL) THEN
      -- Use the cursor that also looks at backup redo logs.
      -- The online parameter is assumed to be TRUE#.  Available and
      -- unavailable are ignored.  Since we are looking at backup redo logs,
      -- pattern cannot be implemented here, so we use this cursor only if
      -- pattern is null.
      deb(DEB_OPEN, 'translateArcLogSCNRange2');
      OPEN translateArcLogSCNRange2(thread#     => thread#,
                                    fromSCN     => fromSCN,
                                    toSCN       => adjusted_toSCN,
                                    toTime      => untilTime,
                                    needstby    => needstby);
      getArchivedLogCursor       := 'translateArcLogSCNRange2';
      deb(DEB_IN, ' using cursor 2 fromSCN=' ||
          to_char(fromSCN) || ' toSCN=' || to_char(adjusted_toSCN));
   ELSE
      deb(DEB_OPEN, 'translateArcLogSCNRange');
      OPEN translateArcLogSCNRange(thread#     => thread#,
                                   fromSCN     => fromSCN,
                                   toSCN       => adjusted_toSCN,
                                   pattern     => pattern,
                                   statusMask  => mask,
                                   online      => online,
                                   needstby    => needstby);
      getArchivedLogCursor       := 'translateArcLogSCNRange';
   END IF;
   getArchivedLogDuplicates   := duplicates;
   getArchivedLogNoRows.error := -20242;
   getArchivedLogNoRows.msg   := 'No archived logs in the range specified';
   setTransClause(thread  => thread#,
                  fromSCN => fromSCN,
                  toSCN   => adjusted_toSCN,
                  pattern => pattern);
   deb(DEB_EXIT);
END translateArchivedLogSCNRange;
-- Translate an archived log name pattern
------------------------- translateArchivedLogPattern -------------------------
PROCEDURE translateArchivedLogPattern(
   pattern      IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,deleted      IN number         DEFAULT NULL   -- for compatability
  ,online       IN number
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL   -- for compatability
  ,needstby     IN number         DEFAULT NULL)
IS
   mask           number := NVL(statusMask,
                     computeAvailableMask(available, unavailable, deleted, 0));
BEGIN
   deb(DEB_ENTER, 'translateArchivedLogPattern');
   IF (bitand(mask,BSdeleted) != 0 AND pattern IS NULL) THEN
      -- Use the cursor that also looks at union of brl and al tables.
      -- This must be 'archivelog all'. From 8.1.6+, this condition
      -- is checked in krmk.pc (krmkaltr()). Here, to maintain compatibility
      -- with lower version of RMAN (8.1.5-) exec, we move the check here.
      -- This removes us from doing 'compatible' check
     translateArchivedLogSCNRange(
        thread#     => NULL,
        fromscn     => 0,
        toscn       => 281474976710655+1,
        pattern     => NULL,
        statusMask  => mask,
        online      => online,
        duplicates  => duplicates);
   ELSE
     validateState(getArchivedLogCursor);
     deb(DEB_OPEN, 'translateArcLogPattern');
     OPEN translateArcLogPattern(pattern     => pattern,
                                 statusMask  => mask,
                                 online      => online);
     getArchivedLogCursor       := 'translateArcLogPattern';
     getArchivedLogDuplicates   := duplicates;
     getArchivedLogNoRows.error := -20242;
     getArchivedLogNoRows.msg   := 'No archived logs in the range specified';
     setTransClause(pattern => pattern);
   END IF;
   deb(DEB_EXIT);
END translateArchivedLogPattern;
-------------------------- translateArchivedLogCancel -------------------------
PROCEDURE translateArchivedLogCancel
IS
BEGIN
   deb(DEB_ENTER, 'translateArchivedLogCancel');
   IF (getArchivedLogCursor = 'translateArcLogKey') THEN
      CLOSE translateArcLogKey;
   ELSIF (getArchivedLogCursor = 'translateArcLogName') THEN
      CLOSE translateArcLogName;
   ELSIF (getArchivedLogCursor = 'translateArcLogSeqRange') THEN
      CLOSE translateArcLogSeqRange;
   ELSIF (getArchivedLogCursor = 'translateArcLogTimeRange') THEN
      CLOSE translateArcLogTimeRange;
   ELSIF (getArchivedLogCursor = 'translateArcLogSCNRange') THEN
      CLOSE translateArcLogSCNRange;
   ELSIF (getArchivedLogCursor = 'translateArcLogPattern') THEN
      CLOSE translateArcLogPattern;
   END IF;
   getArchivedLogCursor := NULL;                -- we closed it above
   deb(DEB_EXIT);
END translateArchivedLogCancel;
-- This public procedure for 8.1.5 and previous releases.  Recid will be
-- null to indicate end-of-fetch.  That was a bad interface design, but
-- we are stuck with it now.
-------------------------------- getArchivedLog -------------------------------
PROCEDURE getArchivedLog(
   recid        OUT number
  ,stamp        OUT number
  ,thread#      OUT number
  ,sequence#    OUT number
  ,low_scn      OUT number
  ,nxt_scn      OUT number
  ,fname        OUT varchar2
  ,reset_scn    OUT number
  ,block_size   OUT number
  ,blocks       OUT number)
IS
   alRec alRec_t;
BEGIN
   deb(DEB_ENTER, 'getArchivedLog');
<<retry>>
   getArchivedLog(alRec);
   -- Bug 1186598: From 8.1.5- Rman EXEC does union of brl and al tables,
   -- when deleted=TRUE.
   -- Getting a null recid shouldn't affect us.
   -- Return OUT mode args
   recid      := nvl(alRec.recid,0);    -- no null indicator before 8.1.6
   stamp      := nvl(alRec.stamp, 0);   -- no null indicator before 8.1.6
   thread#    := alRec.thread;
   sequence#  := alRec.sequence;
   low_scn    := alRec.lowSCN;
   nxt_scn    := alRec.nextSCN;
   fname      := nvl(alRec.fileName, 'null');   -- no null indicator
   reset_scn  := alRec.rlgSCN;
   block_size := alRec.blockSize;
   blocks     := alRec.blocks;
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      recid := NULL;                    -- indicate end-of-fetch
      stamp := NULL;
      deb(DEB_EXIT, 'with no more records');
END getArchivedLog;
---------------------------------
-- Controlfilecopy Translation --
---------------------------------
-- Translate a controlfilecopy name.
------------------------- translateControlFileCopyName ------------------------
PROCEDURE translateControlFileCopyName(
   fname        IN varchar2
  ,available    IN number           DEFAULT NULL  -- for compatability
  ,unavailable  IN number           DEFAULT NULL  -- for compatability
  ,duplicates   IN number
  ,statusMask   IN binary_integer   DEFAULT NULL) -- for compatability
IS
BEGIN
   deb(DEB_ENTER, 'translateControlFileCopyName');
   -- Replaces ccf_name
   deb(DEB_OPEN, 'findControlfileCopy');
   OPEN findControlfileCopy(pattern            => fname,
                            currentIncarnation => FALSE#,
                            statusMask         => NVL(statusMask,
                             computeAvailableMask(available,unavailable,0,0)));
   -- Initialize singleRow variable
   IF (duplicates = FALSE#) THEN
      getControlFileCopySingleRow := TRUE;
   ELSE
      getControlFileCopySingleRow := FALSE;
   END IF;
   deb(DEB_EXIT);
END translateControlFileCopyName;
------------------------------ getControlFileCopy -----------------------------
PROCEDURE getControlFileCopy(
   rcvRec       IN OUT rcvRec_t)
IS
   getControlFileCopyRowcount   number;
BEGIN
   deb(DEB_ENTER, 'getControlFileCopy');
   IF (NOT findControlfileCopy%ISOPEN) THEN
      deb(DEB_EXIT, 'with error 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
<<nextRow>>
   FETCH findControlfileCopy
    INTO rcvRec;
   IF (findControlfileCopy%NOTFOUND) THEN
      -- Save rowcount before closing cursor
      getControlFileCopyRowcount := findControlfileCopy%ROWCOUNT;
      CLOSE findControlfileCopy;
      IF (getControlFileCopyRowcount = 0) THEN
         deb(DEB_EXIT, 'with error 20220');
         raise_application_error(-20220, 'Controlfile copy does not exist');
      ELSE
         deb(DEB_EXIT, 'with no more records');
         RAISE no_data_found;                   -- signal end-of-fetch
      END IF;
   END IF;
   IF (getControlFileCopySingleRow = TRUE AND
       findControlfileCopy%ROWCOUNT > 1) THEN
      -- We only want a single row, and we've already returned 1 row, so
      -- just treat this as end-of-fetch
      CLOSE findControlfileCopy;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   deb(DEB_EXIT);
END getControlFileCopy;
-- Obsolete as of 8.1.6
------------------------------ getControlFileCopy -----------------------------
PROCEDURE getControlFileCopy(
   recid        OUT number
  ,stamp        OUT number
  ,reset_scn    OUT number
  ,ckp_scn      OUT number
  ,block_size   OUT number)
IS
   rcvRec       rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'getControlFileCopy');
   getControlFileCopy(rcvRec);
   recid      := rcvRec.recid_con;
   stamp      := rcvRec.stamp_con;
   reset_scn  := rcvRec.rlgSCN_act;
   ckp_scn    := rcvRec.toSCN_act;
   block_size := rcvRec.blockSize_con;
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with no more records');
      -- This just means end-of-fetch
      recid := NULL;                    -- signal end-of-fetch to caller
END getControlFileCopy;
------------------------------
-- Datafilecopy Translation --
------------------------------
------------------------------- getDataFileCopy -------------------------------
PROCEDURE getDataFileCopy(
   rcvRec       OUT rcvRec_t
  ,closeCursor IN  boolean DEFAULT FALSE)
IS
   getDataFileCopyRowcount      number;
   local                        rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'getDataFileCopy');
<<nextRow>>
   IF (getDatafileCopyCursor = 'findDatafileCopyKey') THEN
      FETCH findDatafileCopyKey
       INTO local;
      IF (findDatafileCopyKey%NOTFOUND) THEN
         getDataFileCopyRowcount := findDatafileCopyKey%ROWCOUNT;
         CLOSE findDatafileCopyKey;
      END IF;
      IF (closeCursor AND findDatafileCopyKey%ISOPEN) THEN
         CLOSE findDatafileCopyKey;
      END IF;
   ELSIF (getDatafileCopyCursor = 'findDatafileBackup_c') THEN
      IF (getDataFileCopySingleRow = TRUE AND
          findDatafileBackup_c%ROWCOUNT > 1) THEN
         -- We only want a single row, and we've already returned 1 row, so
         -- just treat this as end-of-fetch
         CLOSE findDatafileBackup_c;
         getDatafileCopyCursor := NULL;
         deb(DEB_EXIT, 'with no more records');
         RAISE no_data_found;
      END IF;
      FETCH findDatafileBackup_c
       INTO local;
      IF (findDatafileBackup_c%NOTFOUND) THEN
         getDataFileCopyRowcount := findDatafileBackup_c%ROWCOUNT;
         CLOSE findDatafileBackup_c;
      END IF;
      IF (closeCursor AND findDatafileBackup_c%ISOPEN) THEN
         CLOSE findDatafileBackup_c;
      END IF;
   ELSE
      deb(DEB_EXIT, 'with error 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
   IF (closeCursor) THEN
      getDatafileCopyCursor := NULL;
   END IF;
   IF (getDataFileCopyRowcount IS NOT NULL) THEN
      getDatafileCopyCursor := NULL;
      IF (getDataFileCopyRowcount = 0 AND
          getDatafileCopyNoRows.error IS NOT NULL) THEN
         deb(DEB_EXIT, 'with norows error');
         raise_application_error(getDatafileCopyNoRows.error,
                                 getDatafileCopyNoRows.msg);
      ELSE
         deb(DEB_EXIT, 'with no more records');
         RAISE no_data_found;                   -- signal end-of-fetch
      END IF;
   END IF;
   IF (getDataFileCopyDuplicates = FALSE# AND
       getDataFileCopyLast.dfNumber_obj = local.dfNumber_obj) THEN
      GOTO nextRow;
   END IF;
   getDataFileCopyLast := local;                -- save for duplicate filtering
   rcvRec := local;                             -- set OUT mode arg
   deb(DEB_EXIT);
END getDataFileCopy;
--------------------------- translateDataFileCopyKey --------------------------
PROCEDURE translateDataFileCopyKey(
   cdf_key      IN number
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,statusMask   IN binary_integer DEFAULT NULL)  -- for compatability
IS
BEGIN
   deb(DEB_ENTER, 'translateDataFileCopyKey');
   validateState(getDatafileCopyCursor);
   -- Replaces cursor that used to be in translateDataFileCopyKey
   deb(DEB_OPEN, 'findDataFileCopyKey');
   OPEN findDataFileCopyKey(copyKey            => cdf_key,
                            statusMask         => NVL(statusMask,
                               computeAvailableMask(available, unavailable,
                                                    0, 0)));
   getDatafileCopyCursor       := 'findDatafileCopyKey';
   getDataFileCopyNoRows.error := -20230;
   getDataFileCopyNoRows.msg   := 'Datafile copy does not exist';
   getDataFileCopyDuplicates   := NULL;
   getDataFileCopySingleRow    := NULL;
   deb(DEB_EXIT);
END translateDatafileCopyKey;
-- Obsolete as of 8.1.6
--------------------------- translateDataFileCopyKey --------------------------
PROCEDURE translateDataFileCopyKey(
   cdf_key      IN number
  ,available    IN number
  ,unavailable  IN number
  ,recid        OUT number
  ,stamp        OUT number
  ,file#        OUT number
  ,fname        OUT varchar2
  ,reset_scn    OUT number
  ,create_scn   OUT number
  ,ckp_scn      OUT number
  ,block_size   OUT number
  ,blocks       OUT number)
IS
   rcvRec       rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'translateDataFileCopyKey815');
   translateDataFileCopyKey(cdf_key     => cdf_key,
                            available   => available,
                            unavailable => unavailable);
   getDataFileCopy(rcvRec      => rcvRec,
                   closeCursor => TRUE);
   recid        := rcvRec.recid_con;
   stamp        := rcvRec.stamp_con;
   file#        := rcvRec.dfNumber_obj;
   fname        := rcvRec.fileName_con;
   reset_scn    := rcvRec.rlgSCN_act;
   create_scn   := rcvRec.dfCreationSCN_obj;
   ckp_scn      := rcvRec.toSCN_act;
   block_size   := rcvRec.blockSize_con;
   blocks       := rcvRec.blocks_con;
   deb(DEB_EXIT);
END translateDataFileCopyKey;
-- Translate a datafilecopy name.  The datafile copies are ordered by
-- stamp in order to return most recently created copy first, because it
-- most likely to exist.  Note that datafilecopies that belong to any
-- incarnation of the current database are returned.
-------------------------- translateDatafileCopyName --------------------------
PROCEDURE translateDatafileCopyName(
   fname       IN varchar2
  ,available   IN number         DEFAULT NULL   -- for compatability
  ,unavailable IN number         DEFAULT NULL   -- for compatability
  ,duplicates  IN number
  ,statusMask  IN binary_integer DEFAULT NULL)  -- for compatability
IS
BEGIN
   deb(DEB_ENTER, 'translateDatafileCopyName');
   validateState(getDatafileCopyCursor);
   -- Replaces cdf_name
   deb(DEB_OPEN, 'findDatafileCopy');
   OPEN findDatafileBackup_c(
                        sourcemask   => imageCopy_con_t,
                        pattern      => fname,
                        statusMask   => nvl(statusMask,
                                            computeAvailableMask(available,
                                                                 unavailable,
                                                                 0, 0))
                        );
   getDatafileCopyCursor            := 'findDatafileBackup_c';
   getDatafileCopyNoRows.error      := -20230;
   getDatafileCopyNoRows.msg        := 'Datafile copy does not exist';
   getDatafileCopyDuplicates        := duplicates;
   getDatafileCopyLast.dfNumber_obj := NULL;
   IF (duplicates = FALSE#) THEN
      getDatafileCopySingleRow := TRUE;
   ELSE
      getDatafileCopySingleRow := FALSE;
   END IF;
   deb(DEB_EXIT);
END translateDatafileCopyName;
-- Translate a datafilecopy tag.  The datafilecopies are ordered by file#
-- in order to make the duplicate elimination work and by descending
-- checkpoint scn to return most recent copy first.
-- ### only copies that belong to current database incarnation are returned,
-- We should change this in future to return datafile copies that belong
-- previous incarnations of the database.  The difficulty is that the recovery
-- catalog may also contain datafile copies that belong to "orphaned"
-- incarnation of the database.
--------------------------- translateDataFileCopyTag --------------------------
PROCEDURE translateDataFileCopyTag(
   tag          IN varchar2
  ,available    IN number         DEFAULT NULL   -- for compatability
  ,unavailable  IN number         DEFAULT NULL   -- for compatability
  ,duplicates   IN number
  ,statusMask   IN binary_integer DEFAULT NULL)  -- for compatability
IS
BEGIN
   deb(DEB_ENTER, 'translateDataFileCopyTag');
   validateState(getDatafileCopyCursor);
   -- Replaces cdf_tag.  Note that we look only for ones in the current
   -- incarnation because that is what cdf_tag did.  If access to
   -- datafilecopies in other incarnations is required, it must be done by
   -- key or filename.
   deb(DEB_OPEN, 'findDataFileBackup_c');
   OPEN findDatafileBackup_c(
                         sourcemask   => imageCopy_con_t,
                         tag          => tag,
                         reset_scn    => this_reset_scn,
                         reset_time   => this_reset_time,
                         statusMask   => nvl(statusMask,
                                             computeAvailableMask(available,
                                                                  unavailable,
                                                                  0, 0))
                         );
   getDatafileCopyCursor            := 'findDatafileBackup_c';
   getDataFileCopyNoRows.error      := -20232;
   getDataFileCopyNoRows.msg        := 'Datafile copy tag does not match';
   getDataFileCopyDuplicates        := duplicates;
   getDataFileCopyLast.dfNumber_obj := NULL;
   getDataFileCopySingleRow         := FALSE;
   deb(DEB_EXIT);
END translateDataFileCopyTag;
-- Translate a datafilecopy file number.  The datafile copies are ordered by
-- stamp in order to return most recently created copy first, because it
-- most likely to exist.  Note that datafilecopies that belong to any
-- incarnation of the current database are returned.
-------------------------- translateDatafileCopyFno --------------------------
PROCEDURE translateDatafileCopyFno(
   fno         IN number
  ,available   IN number         DEFAULT NULL
  ,unavailable IN number         DEFAULT NULL
  ,duplicates  IN number
  ,statusMask  IN binary_integer DEFAULT NULL)
IS
BEGIN
   deb(DEB_ENTER, 'translateDatafileCopyFno');
   validateState(getDatafileCopyCursor);
   deb(DEB_OPEN, 'findDatafileBackup_c');
   OPEN findDatafileBackup_c(
                         sourcemask    => imageCopy_con_t,
                         fno           => fno,
                         statusMask    => NVL(statusMask,
                                              computeAvailableMask(available,
                                                                   unavailable,
                                                                   0, 0))
                         );
   getDatafileCopyCursor            := 'findDatafileBackup_c';
   getDatafileCopyNoRows.error      := -20230;
   getDatafileCopyNoRows.msg        := 'Datafile copy does not exist';
   getDatafileCopyDuplicates        := duplicates;
   getDatafileCopyLast.dfNumber_obj := NULL;
   IF (duplicates = FALSE#) THEN
      getDatafileCopySingleRow := TRUE;
   ELSE
      getDatafileCopySingleRow := FALSE;
   END IF;
   deb(DEB_EXIT);
END translateDatafileCopyFno;
-- Obsolete as of 8.1.6
------------------------------- getDataFileCopy -------------------------------
PROCEDURE getDataFileCopy(
   recid OUT number
  ,stamp OUT number
  ,file# OUT number
  ,fname OUT varchar2
  ,reset_scn OUT number
  ,create_scn OUT number
  ,ckp_scn OUT number
  ,block_size OUT number
  ,blocks OUT number)
IS
   rcvRec       rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'getDataFileCopy');
   getDataFileCopy(rcvRec);
   recid        := rcvRec.recid_con;
   stamp        := rcvRec.stamp_con;
   file#        := rcvRec.dfNumber_obj;
   fname        := rcvRec.fileName_con;
   reset_scn    := rcvRec.rlgSCN_act;
   create_scn   := rcvRec.dfCreationSCN_obj;
   ckp_scn      := rcvRec.toSCN_act;
   block_size   := rcvRec.blockSize_con;
   blocks       := rcvRec.blocks_con;
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      recid := NULL;                    -- signal end-of-fetch to client
      deb(DEB_EXIT, 'with no more records');
END getDataFileCopy;
----------------------------
-- Proxy Copy Translation --
----------------------------
--------------------------------- getProxyCopy --------------------------------
PROCEDURE getProxyCopy(
   rcvRec      OUT rcvRec_t
  ,closeCursor IN  boolean DEFAULT FALSE)
IS
   getProxyCopyRowcount number;
   dummy                rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'getProxyCopy');
   IF (getProxyCopyCursor = 'findProxyCopy') THEN
      FETCH findProxyCopy
       INTO rcvRec;
      IF (findProxyCopy%NOTFOUND) THEN
         getProxyCopyRowcount := findProxyCopy%ROWCOUNT;
         CLOSE findProxyCopy;
      ELSE
         IF (getProxyCopyByHandle) THEN
            -- Make sure there is only 1 row
            FETCH findProxyCopy
             INTO dummy;
            IF (NOT findProxyCopy%NOTFOUND) THEN
               CLOSE findProxyCopy;
               deb(DEB_EXIT, 'with error 20311');
               raise_application_error(-20311, 'Ambiguous proxy copy handle');
            END IF;
         END IF;
      END IF;
      IF (closeCursor AND findProxyCopy%ISOPEN) THEN
         CLOSE findProxyCopy;
      END IF;
   ELSIF (getProxyCopyCursor = 'findProxyCopyKey') THEN
      FETCH findProxyCopyKey
       INTO rcvRec;
      IF (findProxyCopyKey%NOTFOUND) THEN
         getProxyCopyRowcount := findProxyCopyKey%ROWCOUNT;
         CLOSE findProxyCopyKey;
      END IF;
      IF (closeCursor AND findProxyCopyKey%ISOPEN) THEN
         CLOSE findProxyCopyKey;
      END IF;
   ELSE
      deb(DEB_EXIT, 'with errors 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
   IF (closeCursor) THEN
      getProxyCopyCursor := NULL;
   END IF;
   IF (getProxyCopyRowcount IS NOT NULL) THEN
      getProxyCopyCursor := NULL;
      IF (getProxyCopyRowcount = 0 AND
          getProxyCopyNoRows.error IS NOT NULL) THEN
         deb(DEB_EXIT, 'with norows error');
         raise_application_error(getProxyCopyNoRows.error,
                                 getProxyCopyNoRows.msg);
      ELSE
         deb(DEB_EXIT, 'with no more records');
         RAISE no_data_found;                   -- signal end-of-fetch
      END IF;
   END IF;
   deb(DEB_EXIT);
END getProxyCopy;
---------------------------- translateProxyCopyKey ----------------------------
PROCEDURE translateProxyCopyKey(
   pc_key       IN number
  ,deviceType   IN varchar2
  ,available    IN number           DEFAULT NULL   -- for compatability
  ,unavailable  IN number           DEFAULT NULL   -- for compatability
  ,deleted      IN number           DEFAULT NULL   -- for compatability
  ,expired      IN number           DEFAULT NULL   -- for compatability
  ,statusMask   IN binary_integer   DEFAULT NULL)  -- for compatability
IS
BEGIN
   deb(DEB_ENTER, 'translateProxyCopyKey');
   validateState(getProxyCopyCursor);
   deb(DEB_OPEN, 'findProxyCopyKey');
   OPEN findProxyCopyKey(key            => pc_key,
                         deviceType     => deviceType,
                         statusMask     => NVL(statusMask,
                  computeAvailableMask(available, unavailable, deleted,
                                       expired)));
   getProxyCopyCursor       := 'findProxyCopyKey';
   getProxyCopyNoRows.error := -20310;
   getProxyCopyNoRows.msg   := 'proxy copy is missing';
   getProxyCopyByHandle     := FALSE;
   deb(DEB_EXIT);
END translateProxyCopyKey;
-- Obsolete as of 8.1.6
---------------------------- translateProxyCopyKey ----------------------------
PROCEDURE translateProxyCopyKey(
   pc_key       IN number
  ,device_type  IN varchar2
  ,available    IN number
  ,unavailable  IN number
  ,deleted      IN number
  ,recid        OUT number
  ,stamp        OUT number
  ,handle       OUT varchar2)
IS
   rcvRec       rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'translateProxyCopyKey815');
   translateProxyCopyKey(pc_key         => pc_key,
                         deviceType     => device_type,
                         available      => available,
                         unavailable    => unavailable,
                         deleted        => deleted,
                         expired        => unavailable);
   getProxyCopy(rcvRec      => rcvRec,
                closeCursor => TRUE);
   recid  := rcvRec.recid_con;
   stamp  := rcvRec.stamp_con;
   handle := rcvRec.fileName_con;
   deb(DEB_EXIT);
END translateProxyCopyKey;
--------------------------- translateProxyCopyHandle --------------------------
PROCEDURE translateProxyCopyHandle(
   handle       IN varchar2
  ,deviceType   IN varchar2
  ,available    IN number           DEFAULT NULL   -- for compatability
  ,unavailable  IN number           DEFAULT NULL   -- for compatability
  ,deleted      IN number           DEFAULT NULL   -- for compatability
  ,expired      IN number           DEFAULT NULL   -- for compatability
  ,statusMask   IN binary_integer   DEFAULT NULL)  -- for compatability
IS
BEGIN
   deb(DEB_ENTER, 'translateProxyCopyHandle');
   validateState(getProxyCopyCursor);
   deb(DEB_OPEN, 'findProxyCopy');
   OPEN findProxyCopy(handle      => handle,
                      deviceType  => deviceType,
                      statusMask  => NVL(statusMask,
                          computeAvailableMask(available, unavailable, deleted,
                                               expired)));
   getProxyCopyCursor       := 'findProxyCopy';
   getProxyCopyNoRows.error := -20310;
   getProxyCopyNoRows.msg   := 'proxy copy is missing';
   getProxyCopyByHandle     := TRUE;
   deb(DEB_EXIT);
END translateProxyCopyHandle;
-- Obsolete as of 8.1.6
--------------------------- translateProxyCopyHandle --------------------------
PROCEDURE translateProxyCopyHandle(
   handle       IN varchar2
  ,device_type  IN varchar2
  ,available    IN number
  ,unavailable  IN number
  ,deleted      IN number
  ,recid        OUT number
  ,stamp        OUT number)
IS
   rcvRec       rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'translateProxyCopyHandle815');
   translateProxyCopyHandle(handle      => handle,
                            deviceType  => device_type,
                            available   => available,
                            unavailable => unavailable,
                            deleted     => deleted,
                            expired     => unavailable);
   getProxyCopy(rcvRec      => rcvRec,
                closeCursor => TRUE);
   recid  := rcvRec.recid_con;
   stamp  := rcvRec.stamp_con;
   deb(DEB_EXIT);
END translateProxyCopyHandle;
-- Translate a proxy copy tag into a list of proxy copies
---------------------------- translateProxyCopyTag ----------------------------
PROCEDURE translateProxyCopyTag(
   tag         IN varchar2
  ,device_type IN varchar2
  ,available   IN number           DEFAULT NULL   -- for compatability
  ,unavailable IN number           DEFAULT NULL   -- for compatability
  ,deleted     IN number           DEFAULT NULL   -- for compatability
  ,statusMask  IN binary_integer   DEFAULT NULL)  -- for compatability
IS
BEGIN
   deb(DEB_ENTER, 'translateProxyCopyTag');
   validateState(getProxyCopyCursor);
   deb(DEB_OPEN, 'findProxyCopy');
   OPEN findProxyCopy(tag            => tag,
                      deviceType     => device_type,
                      statusMask     => NVL(statusMask,
                          computeAvailableMask(available, unavailable, deleted,
                                               unavailable/*expired*/)));
   getProxyCopyCursor       := 'findProxyCopy';
   getProxyCopyNoRows.error := -20310;
   getProxyCopyNoRows.msg   := 'no matching proxy copy found';
   getProxyCopyByHandle     := FALSE;
   deb(DEB_EXIT);
END translateProxyCopyTag;
-- Obsolete as of 8.1.6
--------------------------------- getProxyCopy --------------------------------
PROCEDURE getProxyCopy(
   recid        OUT number
  ,stamp        OUT number
  ,handle       OUT varchar2)
IS
   rcvRec       rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'getProxyCopyHandle');
   getProxyCopy(rcvRec);
   recid  := rcvRec.recid_con;
   stamp  := rcvRec.stamp_con;
   handle := rcvRec.fileName_con;
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      recid := NULL;                    -- indicate end-of-fetch
      deb(DEB_EXIT, 'with no more records');
END getProxyCopy;
------------------------------
-- Backup Piece Translation --
------------------------------
-------------------------------- getBackupPiece -------------------------------
PROCEDURE getBackupPiece(
   bpRec        OUT bpRec_t
  ,closeCursor  IN  boolean DEFAULT FALSE)
IS
   dummy        bpRec_t;
   local        bpRec_t;
   eof          boolean := FALSE;
BEGIN
   deb(DEB_ENTER, 'getBackupPiece');
   IF (getBackupPieceDuplicates = FALSE# AND
       getBackupPieceDeviceType IS NULL) THEN
      -- If duplicate filtering is requested, it means only 1 copy of each
      -- piece is wanted.  The deviceType must be specified in this case.
      -- If not, then raise an exception.
      deb(DEB_EXIT, 'with error 20000');
      raise_application_error(-20000, 'deviceType must be specified');
   END IF;
<<nextRow>>
   IF (getBackupPieceCursor = 'findBackupPieceBpKey') THEN
      FETCH findBackupPieceBpKey
       INTO local;
      IF (findBackupPieceBpKey%NOTFOUND) THEN
         eof := TRUE;
         CLOSE findBackupPieceBpKey;
      END IF;
      IF (closeCursor AND findBackupPieceBpKey%ISOPEN) THEN
         CLOSE findBackupPieceBpKey;
      END IF;
   ELSIF (getBackupPieceCursor = 'findBackupPieceBsKey') THEN
      FETCH findBackupPieceBsKey
       INTO local;
      IF (findBackupPieceBsKey%NOTFOUND) THEN
         eof := TRUE;
         CLOSE findBackupPieceBsKey;
      END IF;
      IF (closeCursor AND findBackupPieceBsKey%ISOPEN) THEN
         CLOSE findBackupPieceBsKey;
      END IF;
   ELSIF (getBackupPieceCursor = 'findBackupPiece_c') THEN
      FETCH findBackupPiece_c
       INTO local;
      IF (findBackupPiece_c%NOTFOUND) THEN
         eof := TRUE;
         CLOSE findBackupPiece_c;
      ELSE
         IF (getBackupPieceByHandle) THEN
            -- Make sure we can only fetch 1 row.
            FETCH findBackupPiece_c
             INTO dummy;
            IF (NOT findBackupPiece_c%NOTFOUND) THEN
               CLOSE findBackupPiece_c;
               deb(DEB_EXIT, 'with error 20261');
               raise_application_error(-20261, 'Ambiguous backup piece handle');
            END IF;
         END IF;
      END IF;
      IF (closeCursor AND findBackupPiece_c%ISOPEN) THEN
         CLOSE findBackupPiece_c;
      END IF;
   ELSE
      deb(DEB_EXIT, 'with error 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
   IF (closeCursor OR eof) THEN
      getBackupPieceCursor := NULL;
   END IF;
   IF (eof) THEN                                -- if end of fetch
      -- If we've been requested to check that all pieces of the set
      -- have been found, then perform the check.
      IF (getBackupPieceDuplicates = FALSE#) THEN
         -- We don't want duplicates, which means duplicate filtering is
         -- in effect.  We already asserted above that a deviceType has
         -- been specified, so we know filtering is possible.
         IF (getBackupPieceExpectedPieces IS NOT NULL AND
             (getBackupPieceAvailableMask IS NULL  OR
              bitand(getBackupPieceAvailableMask,
                     dbms_rcvman.BSpartial_avail) = 0) AND
             getBackupPieceExpectedPieces <> getBackupPiecePieceCount) THEN
             deb(DEB_EXIT, 'with error 20216');
             raise_application_error(-20216, 'Backup piece is missing');
         END IF;
      END IF;
      IF (getBackupPiecePieceCount = 0 AND
          getBackupPieceNoRows.error IS NOT NULL) THEN
         deb(DEB_EXIT, 'with norows error');
         raise_application_error(getBackupPieceNoRows.error,
                                 getBackupPieceNoRows.msg);
      ELSE
         deb(DEB_EXIT, 'no more records');
         RAISE no_data_found;
      END IF;
   END IF;
   IF (getBackupPieceDuplicates = FALSE#) THEN
      -- Client does not want duplicates, so lets filter out duplicate
      -- pieces.
      IF (local.pieceNumber = getBackupPieceLast.pieceNumber) THEN
         -- This is a duplicate piece
         GOTO nextRow;
      END IF;
   END IF;
   getBackupPieceLast := local;
   bpRec := local;                              -- set OUT mode arg
   getBackupPiecePieceCount := getBackupPiecePieceCount + 1;
   deb(DEB_EXIT);
END getBackupPiece;
--------------------------- translateBackupPieceKey ---------------------------
PROCEDURE translateBackupPieceKey(
   key          IN number
  ,available    IN number             DEFAULT TRUE#
  ,unavailable  IN number             DEFAULT TRUE#
  ,expired      IN number             DEFAULT TRUE#
  ,statusMask   IN binary_integer     DEFAULT NULL)  -- for compatability
IS
BEGIN
   -- Open cursor to lookup bp by primary key.  Treat expired backup pieces
   -- as if they were unavailable.  We do this only because the interface
   -- to translateBackupPieceKey was not enhanced to have an "expired"
   -- argument when status 'X' was introduced.
   -- Replaces the cursor that was in the 8.1.x translateBackupPieceKey.
   deb(DEB_ENTER, 'translateBackupPieceKey');
   findBackupPiece(bpKey       => key,
                   statusMask  => NVL(statusMask,
                computeAvailableMask(available, unavailable, 0, unavailable)));
   getBackupPieceNoRows.error   := -20260;
   getBackupPieceNoRows.msg     := 'Backup piece is missing';
   getBackupPieceAvailableMask  := statusMask;
   deb(DEB_EXIT);
END translateBackupPieceKey;
--------------------------- translateBackupPieceKey ---------------------------
PROCEDURE translateBackupPieceKey(
   bp_key       IN number
  ,available    IN number
  ,unavailable  IN number
  ,recid        OUT number
  ,stamp        OUT number
  ,handle       OUT varchar2
  ,set_stamp    OUT number
  ,set_count    OUT number
  ,piece#       OUT number)
IS
   bpRec        bpRec_t;
BEGIN
   deb(DEB_ENTER, 'translateBackupPieceKey');
   -- Open cursor to lookup bp by primary key.  Treat expired backup pieces
   -- as if they were unavailable.  We do this only because the interface
   -- to translateBackupPieceKey was not enhanced to have an "expired"
   -- argument when status 'X' was introduced.  It should have been enhanced
   -- to have one, but since it was not, we have to assume the most
   -- reasonable default value.
   -- Replaces the cursor that was in the 8.1.x translateBackupPieceKey.
   translateBackupPieceKey(key => bp_key,
                   statusMask  =>
                computeAvailableMask(available, unavailable, 0,
                                     unavailable/*expired*/));
   getBackupPiece(bpRec       => bpRec,
                  closeCursor => TRUE);
   recid     := bpRec.recid;
   stamp     := bpRec.stamp;
   handle    := bpRec.handle;
   set_stamp := bpRec.setStamp;
   set_count := bpRec.setCount;
   piece#    := bpRec.pieceNumber;
   deb(DEB_EXIT);
END translateBackupPieceKey;
-------------------------- translateBackupPieceHandle -------------------------
PROCEDURE translateBackupPieceHandle(
   handle       IN varchar2
  ,deviceType   IN varchar2
  ,available    IN number             DEFAULT NULL   -- for compatability
  ,unavailable  IN number             DEFAULT NULL   -- for compatability
  ,expired      IN number             DEFAULT NULL   -- for compatability
  ,statusMask   IN binary_integer     DEFAULT NULL)  -- for compatability
IS
BEGIN
   deb(DEB_ENTER, 'translateBackupPieceHandle');
   findBackupPiece(handle      => handle,
                   deviceType  => deviceType,
                   statusMask  => NVL(statusMask,
                  computeAvailableMask(available, unavailable, 0, expired)));
   getBackupPieceNoRows.error   := -20260;
   getBackupPieceNoRows.msg     := 'Backup piece is missing';
   getBackupPieceByHandle       := TRUE;
   getBackupPieceAvailableMask  := statusMask;
   deb(DEB_EXIT);
END translateBackupPieceHandle;
-------------------------- translateBackupPieceHandle -------------------------
PROCEDURE translateBackupPieceHandle(                     -- only used in 8.1.6
   handle       IN varchar2
  ,device_type  IN varchar2
  ,available    IN number
  ,unavailable  IN number
  ,recid        OUT number
  ,stamp        OUT number
  ,set_stamp    OUT number
  ,set_count    OUT number
  ,piece#       OUT number)
IS
   bpRec        bpRec_t;
BEGIN
   deb(DEB_ENTER, 'translateBackupPieceHandle816');
   translateBackupPieceHandle(handle      => handle,
                              deviceType  => device_type,
                              statusMask  =>
                             computeAvailableMask(available, unavailable, 0,
                                                  unavailable/*expired*/));
   getBackupPiece(bpRec       => bpRec,
                  closeCursor => TRUE);
   recid     := bpRec.recid;
   stamp     := bpRec.stamp;
   set_stamp := bpRec.setStamp;
   set_count := bpRec.setCount;
   piece#    := bpRec.pieceNumber;
   deb(DEB_EXIT);
END translateBackupPieceHandle;
-- Translate a backup piece tag into a list of backup pieces
--------------------------- translateBackupPieceTag ---------------------------
PROCEDURE translateBackupPieceTag(
   tag         IN varchar2
  ,available   IN number             DEFAULT NULL     -- for compatability
  ,unavailable IN number             DEFAULT NULL     -- for compatability
  ,statusMask  IN binary_integer     DEFAULT NULL)
IS
BEGIN
   deb(DEB_ENTER, 'translateBackupPieceTag');
   findBackupPiece(tag         => tag,
                   statusMask  => NVL(statusMask,
                  computeAvailableMask(available, unavailable, 0,
                                       /* expired = */unavailable)));
   deb(DEB_EXIT);
END translateBackupPieceTag;
-------------------------- translateBackupPieceBSKey --------------------------
PROCEDURE translateBackupPieceBSKey(
   key          IN number
  ,tag          IN varchar2        DEFAULT NULL
  ,deviceType   IN varchar2        DEFAULT NULL
  ,pieceCount   IN number
  ,duplicates   IN number          DEFAULT TRUE#
  ,copyNumber   IN number          DEFAULT NULL
  ,available    IN number          DEFAULT TRUE#
  ,unavailable  IN number          DEFAULT FALSE#
  ,deleted      IN number          DEFAULT FALSE#
  ,expired      IN number          DEFAULT FALSE#
  ,statusMask   IN binary_integer  DEFAULT NULL)
IS
BEGIN
   deb(DEB_ENTER, 'translateBackupPieceBSKey');
   findBackupPiece(bsKey       => key,
                   tag         => tag,
                   deviceType  => deviceType,
                   copyNumber  => copyNumber,
                   statusMask  => NVL(statusMask,
              computeAvailableMask(available, unavailable, deleted, expired)));
   getBackupPieceDuplicates     := duplicates;
   getBackupPieceExpectedPieces := pieceCount;
   getBackupPieceAvailableMask  := statusMask;
   deb(DEB_EXIT);
END translateBackupPieceBSKey;
-- Obsolete as of 8.1.6
---------------------------- translateBackupSetKey ----------------------------
PROCEDURE translateBackupSetKey(
   bs_key          IN  number
  ,device_type     IN  varchar2
  ,available       IN  number
  ,unavailable     IN  number
  ,deleted         IN  number
  ,duplicates      IN  number
  ,backup_type     OUT varchar2
  ,recid           OUT number
  ,stamp           OUT number
  ,set_stamp       OUT number
  ,set_count       OUT number
  ,bslevel         OUT number
  ,completion_time OUT date)
IS
   bsRec           bsRec_t;
BEGIN
   deb(DEB_ENTER, 'translateBackupSetKey815');
   findBackupSet(bsKey => bs_key,               -- Lookup backset by key
                 bsRec => bsRec);
   backup_type     := bsRec.bsType;
   recid           := bsRec.recid;
   stamp           := bsRec.stamp;
   set_stamp       := bsRec.setStamp;
   set_count       := bsRec.setCount;
   bslevel         := bsRec.level;
   completion_time := bsRec.compTime;
   -- Open cursor to lookup bp by backup set key.  Treat expired pieces
   -- as if they were unavailable.  We do this only because the interface
   -- to translateBackupSetKey was not enhanced to have an "expired"
   -- argument when status 'X' was introduced.  It should have been enhanced
   -- to have one, but since it was not, we have to assume the most
   -- reasonable default value.
   -- Replaces bsq1
   translateBackupPieceBSKey(key         => bs_key,
                             deviceType  => device_type,
                             pieceCount  => bsRec.pieceCount,
                             available   => available,
                             unavailable => unavailable,
                             deleted     => deleted,
                             expired     => unavailable);
   getBackupPieceDuplicates := duplicates;
   IF (device_type IS NULL) THEN
      -- The pre-8.1.6 RMAN is broken.  When doing a LIST (surprise surprise)
      -- it calls this routine with device_type NULL, but the duplicates
      -- flag is FALSE# (don't want duplicates).  This makes no sense because
      -- we can do duplicate filtering only when a device type is specified.
      -- The old version of this package tolerated this client behaviour, but
      -- this version is more strict and will raise an exception.  So to avoid
      -- getting an exception when the old RMAN is calling us, set the
      -- duplicates flag to TRUE#.  This package will then behave the same
      -- as the old one.
      getBackupPieceDuplicates := TRUE#;        -- yes, we want duplicates
   END IF;
   IF (getBackupPieceDuplicates = FALSE#) THEN
      -- If we don't want duplicate pieces, then we are probably planning
      -- to access the backup set, so tell getBackupPiece to perform the
      -- missing piece check.
      getBackupPieceExpectedPieces := bsRec.pieceCount;
   END IF;
   deb(DEB_EXIT);
END translateBackupSetKey;
-- Obsolete as of 8.1
---------------------------- translateBackupSetKey ----------------------------
PROCEDURE translateBackupSetKey(
   bs_key          IN  number
  ,device_type     IN  varchar2
  ,available       IN  number
  ,unavailable     IN  number
  ,deleted         IN  number
  ,duplicates      IN  number
  ,backup_type     OUT varchar2
  ,recid           OUT number
  ,stamp           OUT number)
IS
   set_stamp       number;
   set_count       number;
   bslevel         number;
   completion_time date;
BEGIN
   deb(DEB_ENTER, 'translateBackupSetKey80');
   translateBackupSetKey(bs_key, device_type, available, unavailable, deleted,
                         duplicates, backup_type, recid, stamp, set_stamp,
                         set_count, bslevel, completion_time);
   deb(DEB_EXIT);
END translateBackupSetKey;
-- Obsolete as of 8.1.6
--------------------------- translateBackupSetRecid ---------------------------
PROCEDURE translateBackupSetRecid(
   recid       IN  number
  ,stamp       IN  number
  ,device_type IN  varchar2
  ,bs_key      OUT number
  ,bslevel     OUT number
  ,completed   OUT date)
IS
   bsRec                bsRec_t;
   pieceCount           number;
   validationRec        validBackupSetRec_t;
   gotRecord            number;
   duplicates_flag      number;
BEGIN
   deb(DEB_ENTER, 'translateBackupSetRecid815');
   findBackupSet(recid => recid,
                 stamp => stamp,
                 bsRec => bsRec);
   bs_key    := bsRec.key;
   bslevel   := bsRec.level;
   completed := bsRec.compTime;
   -- See if all pieces are available from the same copy#.  We already
   -- know that the backupset is valid because we wouldn't be here
   -- otherwise.
   -- NOTE:  device_type is null if doing REPORT OBSOLETE
   findValidBackupSet(backupSetRec              => bsRec,
                      tag                       => restoreTag,
                      deviceType                => device_type,
                      available                 => TRUE#);
   gotRecord := getValidBackupSet(validBackupSetRec => validationRec);
   IF (getValidBackupSetCursor = 'findValidBackupSet_c') THEN
      CLOSE findValidBackupSet_c;
   ELSIF (getValidBackupSetCursor = 'findValidBackupSet1P_c') THEN
      CLOSE findValidBackupSet1P_c;
   END IF;
   IF (gotRecord = FALSE#) THEN
      -- Allow a mix of copy#s.  It is probably the case that a backup piece
      -- is missing and getBackupPiece will raise that error.  I don't
      -- know how we could have gotten here in that case, but getBackupPiece
      -- will do the right thing.
      validationRec.copyNumber := NULL;
   END IF;
   IF (device_type IS NULL) THEN
      -- This is the REPORT OBSOLETE case
      duplicates_flag := TRUE#;
   ELSE
      -- This is the normal case (restore/recover)
      duplicates_flag := FALSE#;
   END IF;
   translateBackupPieceBSKey(key         => bsRec.key,
                             tag         => validationRec.tag,
                             deviceType  => device_type,
                             pieceCount  => bsRec.pieceCount,
                             duplicates  => duplicates_flag,
                             copyNumber  => validationRec.copyNumber,
                             available   => TRUE#);
   deb(DEB_EXIT);
END translateBackupSetRecid;
-- Obsolete as of 8.1
--------------------------- translateBackupSetRecid ---------------------------
PROCEDURE translateBackupSetRecid(
   recid       IN  number
  ,stamp       IN  number
  ,device_type IN  varchar2)
IS
   bs_key    number;
   bslevel   number;
   completed date;
BEGIN
   deb(DEB_ENTER, 'translateBackupSetRecid80');
   translateBackupSetRecid(recid, stamp, device_type, bs_key, bslevel,
                          completed);
   deb(DEB_EXIT);
END translateBackupSetRecid;
-- Obsolete as of 8.1.6
-------------------------------- getBackupPiece -------------------------------
PROCEDURE getBackupPiece(
   recid      OUT number
  ,stamp      OUT number
  ,bpkey      OUT number
  ,set_stamp  OUT number
  ,set_count  OUT number
  ,piece#     OUT number
  ,copy#      OUT number
  ,status     OUT varchar2
  ,completion OUT date
  ,handle     OUT varchar2)
IS
   bpRec      bpRec_t;
BEGIN
   deb(DEB_ENTER, 'getBackupPiece815');
   getBackupPiece(bpRec);
   recid        := bpRec.recid;
   stamp        := bpRec.stamp;
   bpkey        := bpRec.key;
   set_stamp    := bpRec.setStamp;
   set_count    := bpRec.setCount;
   piece#       := bpRec.pieceNumber;
   copy#        := bpRec.copyNumber;
   status       := bpRec.status;
   completion   := bpRec.compTime;
   handle       := bpRec.handle;
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with no more records');
      bpRec.recid := NULL;              -- indicate end-of-fetch to client
END getBackupPiece;
-- Obsolete as of 8.1
-------------------------------- getBackupPiece -------------------------------
PROCEDURE getBackupPiece(
   recid     OUT number
  ,stamp     OUT number
  ,set_stamp OUT number
  ,set_count OUT number
  ,piece#    OUT number
  ,handle    OUT varchar2)
IS
   bpRec     bpRec_t;
BEGIN
   deb(DEB_ENTER, 'getBackupPiece80');
   getBackupPiece(bpRec);
   recid        := bpRec.recid;
   stamp        := bpRec.stamp;
   set_stamp    := bpRec.setStamp;
   set_count    := bpRec.setCount;
   piece#       := bpRec.pieceNumber;
   handle       := bpRec.handle;
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      bpRec.recid := NULL;              -- indicate end-of-fetch to client
      deb(DEB_EXIT, 'with no more records');
END getBackupPiece;
----------------------------
-- Backup Set Translation --
----------------------------
---------------------------- translateBackupSetKey ----------------------------
PROCEDURE translateBackupSetKey(
   key        IN  number
  ,bsRec      OUT bsRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'translateBackupSetKey');
   findBackupSet(bsKey => key,
                 bsRec => bsRec);
   deb(DEB_EXIT);
END translateBackupSetKey;
------------------------
-- Controlfile Backup --
------------------------
----------------------------- getControlfileBackup ----------------------------
FUNCTION getControlfileBackup(
   rcvRec       OUT rcvRec_t)
RETURN number IS
   found        boolean := FALSE;
   ccfrec       rcvRec_t;
   bcfrec       rcvRec_t;
   xcfrec       rcvRec_t;
   tag          bp.tag%TYPE;
   val_rc       binary_integer;
   rcvRecCursor rcvRecCursor_t;
   validateRec  validBackupSetRec_t;
BEGIN
   deb(DEB_ENTER, 'getControlfileBackup');
   validateState(null);
   ccfrec.toSCN_act := 0;
   bcfrec.toSCN_act := 0;
   xcfrec.toSCN_act := 0;
   IF (restoreSource = COPY OR restoreSource IS NULL) THEN
      -- Replaces ccfq
      deb(DEB_OPEN, 'findControlfileCopy');
      OPEN findControlfileCopy(currentIncarnation => TRUE#,
                               tag                => restoreTag,
                               untilSCN           => untilSCN,
                               statusMask         => BSavailable,
                               needstby           => onlyStandby);
      LOOP
         FETCH findControlfileCopy
          INTO ccfrec;
         EXIT WHEN findControlfileCopy%NOTFOUND;
         deb(DEB_PRINT, 'getControlfileBackup found a controlfilecopy:');
         printRcvRec(ccfRec);
         IF (NOT diskDevice) THEN
            -- remember that we found one available copy
            found := TRUE;
            ccfrec.toSCN_act := 0;              -- do not use this one
         END IF;
         EXIT;  -- always return the first copy returned by the query
      END LOOP;
      CLOSE findControlfileCopy;
   END IF;
   IF (restoreSource = BACKUP OR restoreSource IS NULL) THEN
      -- Replaces bcfq
      deb(DEB_OPEN, 'findControlfileBackup');
      OPEN findControlfileBackup_c(currentIncarnation => TRUE#,
                                   untilSCN           => untilSCN,
                                   needstby           => onlyStandby);
      -- Find optimal backup set
      LOOP
         FETCH findControlfileBackup_c
          INTO bcfrec;
         EXIT WHEN findControlfileBackup_c%NOTFOUND;
         deb(DEB_PRINT, 'getControlfileBackup found a controlfile backup:');
         printRcvRec(bcfRec);
         val_rc := validateBackupSet(
            backupSetRec           => bcfrec,
            tag                    => restoreTag,
            tagMatchRequired       => TRUE,
            checkDeviceIsAllocated => TRUE,
            availableMask          => BSavailable,
            validRec               => validateRec);
         IF (val_rc = SUCCESS) THEN
            bcfRec.tag_con        := validateRec.tag;
            bcfRec.deviceType_con := validateRec.deviceType;
            bcfRec.copyNumber_con := validateRec.copyNumber;
            -- Return the first one that we find
            EXIT;
         END IF;
         bcfrec.toSCN_act := 0;                 -- do not use this one
         IF (val_rc = dbms_rcvman.AVAILABLE) THEN
            -- remember that we encountered at least one available backup
            found := TRUE;
         END IF;
      END LOOP;
      CLOSE findControlfileBackup_c;
      -- Replaces xcfq
      deb(DEB_OPEN, 'findControlfileProxyCopy');
      OPEN findControlfileProxyCopy(currentIncarnation => TRUE#,
                                    tag                => restoreTag,
                                    untilSCN           => untilSCN,
                                    statusMask         => BSavailable,
                                    needstby           => onlyStandby);
      -- Find optimal proxy copy
      LOOP
         FETCH findControlfileProxyCopy
          INTO xcfrec;
         EXIT WHEN findControlfileProxyCopy%NOTFOUND;
         deb(DEB_PRINT, 'getControlfileBackup found a controlfile proxy copy:');
         printRcvRec(xcfRec);
         IF (isDeviceTypeAllocated(xcfrec.deviceType_con) = TRUE#) THEN
            -- Return the first one that we find
            EXIT;
         END IF;
         -- remember that we encountered at least one available backup
         found := TRUE;
         xcfrec.toSCN_act := 0;                 -- do not use this one
      END LOOP;
      CLOSE findControlfileProxyCopy;
   END IF;
   -- Return the backup or the copy depending on which one has the highest
   -- checkpoint scn.  In case the scns are equal and != 0 return the copy.
   -- If both are 0 then return nothing (all NULLs).
   IF (xcfrec.toSCN_act > greatest(ccfrec.toSCN_act, bcfrec.toSCN_act)) THEN
      rcvRec := xcfrec;
   ELSIF (bcfrec.toSCN_act > ccfrec.toSCN_act) THEN
      rcvRec := bcfrec;
   ELSIF (ccfrec.toSCN_act > 0) THEN
      rcvRec := ccfrec;
   ELSE
      deb(DEB_PRINT, 'getControlfileBackup found no backup');
      IF (found) THEN
      deb(DEB_EXIT, 'with: AVAILABLE');
         RETURN dbms_rcvman.AVAILABLE;
      ELSE
      deb(DEB_EXIT, 'with: UNAVAILABLE');
         RETURN dbms_rcvman.UNAVAILABLE;
      END IF;
   END IF;
   deb(DEB_EXIT, 'with: SUCCESS');
   RETURN SUCCESS;
END getControlfileBackup;
-- This is for 8.0.4 compatibility
---------------------------- findControlFileBackup ----------------------------
FUNCTION findControlFileBackup(
   type         OUT number
  ,recid        OUT number
  ,stamp        OUT number
  ,fname        OUT varchar2
  ,device_type  OUT varchar2
  ,ckp_scn      OUT number)
RETURN number IS
   rcvRec       rcvRec_t;
   rc           number;
BEGIN
   deb(DEB_ENTER, 'findControlFileBackup804');
   rc := getControlfileBackup(rcvRec);
   IF (rc = SUCCESS) THEN
      IF (rcvRec.type_con = imageCopy_con_t) THEN
         type := COPY;
      ELSIF (rcvRec.type_con = backupSet_con_t) THEN
         type := BACKUP;
      ELSIF (rcvRec.type_con = proxyCopy_con_t) THEN
         type := PROXY;
      ELSE
         -- This is an unknown container type.
         deb(DEB_EXIT, 'with: UNAVAILABLE');
         RETURN dbms_rcvman.UNAVAILABLE;
      END IF;
      IF (type = BACKUP) THEN
         recid := rcvRec.bsRecid_con;
         stamp := rcvRec.bsStamp_con;
      ELSE
         recid := rcvRec.recid_con;
         stamp := rcvRec.stamp_con;
      END IF;
      fname       := rcvRec.fileName_con;
      device_type := rcvRec.deviceType_con;
      ckp_scn     := rcvRec.toSCN_act;
      deb(DEB_EXIT, 'with: SUCCESS');
      RETURN SUCCESS;
   ELSE
      deb(DEB_EXIT, 'with: '||to_char(rc));
      RETURN rc;
   END IF;
   deb(DEB_EXIT);
END findControlFileBackup;
-- Obsolete as of 8.1.6
---------------------------- findControlFileBackup ----------------------------
FUNCTION findControlFileBackup(
   type         OUT number
  ,recid        OUT number
  ,stamp        OUT number
  ,fname        OUT varchar2
  ,device_type  OUT varchar2
  ,ckp_scn      OUT number
  ,rlg_scn      OUT number
  ,blksize      OUT number)
RETURN number IS
   rcvRec       rcvRec_t;
   rc           number;
BEGIN
   deb(DEB_ENTER, 'findControlFileBackup815');
   rc := getControlfileBackup(rcvRec);
   IF (rc = SUCCESS) THEN
      IF (rcvRec.type_con = imageCopy_con_t) THEN
         type := COPY;
      ELSIF (rcvRec.type_con = backupSet_con_t) THEN
         type := BACKUP;
      ELSIF (rcvRec.type_con = proxyCopy_con_t) THEN
         type := PROXY;
         rcvRec_last := rcvRec;         -- save for translateProxyDFRecid
      ELSE
         -- This is an unknown container type.
         deb(DEB_EXIT, 'with: UNAVAILABLE');
         RETURN dbms_rcvman.UNAVAILABLE;
      END IF;
      IF (type = BACKUP) THEN
         recid := rcvRec.bsRecid_con;
         stamp := rcvRec.bsStamp_con;
      ELSE
         recid := rcvRec.recid_con;
         stamp := rcvRec.stamp_con;
      END IF;
      fname       := rcvRec.fileName_con;
      device_type := rcvRec.deviceType_con;
      ckp_scn     := rcvRec.toSCN_act;
      rlg_scn     := rcvRec.rlgSCN_act;
      blksize     := rcvRec.blockSize_con;
      deb(DEB_EXIT, 'with: SUCCESS');
      RETURN SUCCESS;
   ELSE
      deb(DEB_EXIT, 'with: '||to_char(rc));
      RETURN rc;
   END IF;
END findControlFileBackup;
-------------------
-- SPFILE Backup --
-------------------
----------------------------- getSpFileBackup ----------------------------
FUNCTION getSpfileBackup(
   rcvRec       OUT rcvRec_t)
RETURN number IS
   found        boolean := FALSE;
   bsfrec       rcvRec_t;
   tag          bp.tag%TYPE;
   val_rc       binary_integer;
   validateRec  validBackupSetRec_t;
BEGIN
   deb(DEB_ENTER, 'getSpfileBackup');
   validateState(null);
   -- Open the cursor
   OPEN findSpfileBackup_c(untilTime => untilTime);
   -- Find optimal backup set
   LOOP
      FETCH findSpfileBackup_c
       INTO bsfrec;
      EXIT WHEN findSpfileBackup_c%NOTFOUND;
      deb(DEB_PRINT, 'getSpfileBackup found an SPFILE backup:');
      printRcvRec(bsfRec);
      val_rc := validateBackupSet(
            backupSetRec           => bsfrec,
            tag                    => restoreTag,
            tagMatchRequired       => TRUE,
            checkDeviceIsAllocated => TRUE,
            availableMask          => dbms_rcvman.BSavailable,
            validRec               => validateRec);
      IF (val_rc = SUCCESS) THEN
         bsfrec.tag_con        := validateRec.tag;
         bsfrec.deviceType_con := validateRec.deviceType;
         bsfrec.copyNumber_con := validateRec.copyNumber;
         -- Return the first one that we find
         EXIT;
      END IF;
      bsfrec.toTime_act := to_date(null);       -- do not use this one
      IF (val_rc = dbms_rcvman.AVAILABLE) THEN
         -- remember that we encountered at least one available backup
         found := TRUE;
      END IF;
   END LOOP;
   -- close the cursor
   CLOSE findSpfileBackup_c;
   IF (bsfrec.toTime_act IS NOT NULL) THEN
      rcvRec := bsfrec;
   ELSE
      IF (found) THEN
         deb(DEB_EXIT, 'with: AVAILABLE');
         RETURN dbms_rcvman.AVAILABLE;
      ELSE
         deb(DEB_EXIT, 'with: UNAVAILABLE');
         RETURN dbms_rcvman.UNAVAILABLE;
      END IF;
   END IF;
   deb(DEB_EXIT, 'with: SUCCESS');
   RETURN SUCCESS;
END getSpfileBackup;
-------------------------
-- Archived Log Backup --
-------------------------
---------------------------- findArchivedLogBackup ----------------------------
PROCEDURE findArchivedLogBackup(
   thread    IN number
  ,sequence  IN number
  ,lowSCN    IN number)
IS
BEGIN
   deb(DEB_ENTER, 'findArchivedLogBackup');
   validateState(null);
   -- RMAN always looks for the log on disk before calling this, so we only
   -- need to look for archivelog backup sets here.
   -- Note that proxy copy for archivelogs is not supported.
   deb(DEB_OPEN, 'findArcLogBackup');
   OPEN findArcLogBackup(currentIncarnation => TRUE#,
                         thread             => thread,
                         sequence           => sequence,
                         lowSCN             => lowSCN);
   deb(DEB_EXIT);
END findArchivedLogBackup;
----------------------------- getArchivedLogBackup ----------------------------
FUNCTION getArchivedLogBackup(
   rcvRec       OUT rcvRec_t)
RETURN binary_integer IS
   myRcvRec     rcvRec_t;
   validRec     validBackupSetRec_t;
   valRC        number;
   found        boolean := FALSE;
BEGIN
   deb(DEB_ENTER, 'getArchivedLogBackup');
   LOOP
      FETCH findArcLogBackup
       INTO myRcvRec;
      IF (findArcLogBackup%NOTFOUND) THEN
         CLOSE findArcLogBackup;
         IF (found) THEN
            deb(DEB_EXIT, 'with: AVAILABLE');
            RETURN dbms_rcvman.AVAILABLE;
         ELSE
            deb(DEB_EXIT, 'with: UNAVAILABLE');
            RETURN dbms_rcvman.UNAVAILABLE;
         END IF;
      END IF;
      valRC :=
         validateBackupSet(backupSetRec           => myRcvRec,
                           checkDeviceIsAllocated => TRUE,
                           tag                    => restoreTag,
                           availableMask          => dbms_rcvman.BSavailable,
                           validRec               => validRec);
      IF (valRC = SUCCESS) THEN
         CLOSE findArcLogBackup;
         rcvRec := myRcvRec;
         rcvRec.deviceType_con := validRec.deviceType;
         rcvRec.tag_con        := validRec.tag;
         rcvRec.copyNumber_con := validRec.copyNumber;
         deb(DEB_EXIT, 'with: SUCCESS');
         RETURN SUCCESS;
      ELSIF (valRC = dbms_rcvman.AVAILABLE) THEN
         found := TRUE;
      END IF;
   END LOOP;
   deb(DEB_EXIT);
END getArchivedLogBackup;
-- Obsolete as of 8.1.6
---------------------------- findArchivedLogBackup ----------------------------
FUNCTION findArchivedLogBackup(
   thread#      IN number
  ,sequence#    IN number
  ,low_scn      IN number
  ,type         OUT number
  ,recid        OUT number
  ,stamp        OUT number
  ,device_type  OUT varchar2)
RETURN number IS
   rcvRec       rcvRec_t;
   RC           binary_integer;
BEGIN
   deb(DEB_ENTER, 'findArchivedLogBackup');
   -- NOTE:  The previous implementation of this checked the restore_from
   -- variable.  This is really not necessary as all RMAN versions always
   -- called setFrom(backup) before calling this procedure.
   findArchivedLogBackup(thread#, sequence#, low_scn);
   RC := getArchivedLogbackup(rcvRec);
   IF (RC = SUCCESS) THEN
      type        := BACKUP;
      recid       := rcvRec.bsRecid_con;
      stamp       := rcvRec.bsStamp_con;
      device_type := rcvRec.deviceType_con;
   END IF;
   deb(DEB_EXIT, 'with: '||to_char(RC));
   RETURN RC;
END findArchivedLogBackup;
---------------
-- List Copy --
---------------
------------------------- listTranslateControlfileCopy ------------------------
PROCEDURE listTranslateControlfileCopy(
   tag             IN varchar2
  ,completedAfter  IN date
  ,completedBefore IN date
  ,statusMask      IN binary_integer DEFAULT
                        BSavailable+BSunavailable+BSexpired) -- default for 8.1
IS
BEGIN
   deb(DEB_ENTER, 'listTranslateControlfileCopy');
   IF (findControlfileCopy%ISOPEN) THEN -- should not be open
      CLOSE findControlfileCopy;
   END IF;
   -- Replaces the lccf cursor
   deb(DEB_OPEN, 'findControlfileCopy');
   OPEN findControlfileCopy(currentIncarnation => TRUE#,
                            tag                => tag,
                            completedAfter     => completedAfter,
                            completedBefore    => completedBefore,
                            statusMask         => statusMask);
   deb(DEB_EXIT);
END listTranslateControlfileCopy;
---------------------------- listGetControlfileCopy ---------------------------
PROCEDURE listGetControlfileCopy(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'listGetControlfileCopy');
   FETCH findControlfileCopy
    INTO rcvRec;
   IF (findControlfileCopy%NOTFOUND) THEN
      CLOSE findControlfileCopy;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   -- Do not need to check the allocated device types.  Copies are available
   -- only on type DISK, so we can assume we wouldn't even be here if
   -- a DISK wasn't allocated.
   deb(DEB_EXIT);
END listGetControlfileCopy;
-- Obsolete as of 8.1.6
---------------------------- listGetControlfileCopy ---------------------------
FUNCTION listGetControlfileCopy(
   bcfkey     OUT number,
   ckpscn     OUT number,
   ckptime    OUT date,
   status     OUT varchar2,
   completion OUT date,
   fname      OUT varchar2) RETURN number
IS
   rcvRec     rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'listGetControlfileCopy');
   listGetControlfileCopy(rcvRec);
   bcfkey     := rcvRec.key_con;
   ckpscn     := rcvRec.toSCN_act;
   ckptime    := rcvRec.toTime_act;
   status     := rcvRec.status_con;
   completion := rcvRec.compTime_con;
   fname      := rcvRec.fileName_con;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
END listGetControlfileCopy;
-------------------------- listTranslateDataFileCopy --------------------------
PROCEDURE listTranslateDataFileCopy(
   file#             IN number
  ,creation_change#  IN number
  ,tag               IN varchar2        DEFAULT NULL
  ,file_name_pattern IN varchar2        DEFAULT NULL
  ,completedAfter    IN date            DEFAULT NULL
  ,completedBefore   IN date            DEFAULT NULL
  ,statusMask        IN binary_integer  DEFAULT BSavailable+BSunavailable)
                                                             -- default for 8.1
IS
   creationSCN        number;
   reset_scn          number := NULL;
   reset_time         date   := NULL;
BEGIN
   deb(DEB_ENTER, 'listTranslateDataFileCopy');
   IF (allIncarnations = TRUE#) THEN
      reset_scn  := NULL;
      reset_time := NULL;
      IF (ignoreCreationSCN = TRUE#) THEN
         -- Since the flag is true, we want to list copies of all
         -- incarnations of each datafile number.  Set crescn to NULL so that
         -- the query returns all datafilecopies of a particular file#.
         -- This is used only by RMAN 8.1.5 and prior 8.1 releases.
         creationSCN := NULL;
      ELSE
         creationSCN := creation_change#;
      END IF;
   ELSE
      reset_scn   := this_reset_scn;
      reset_time  := this_reset_time;
      creationSCN := creation_change#;
   END IF;
   -- Replaces lcdf cursor
   deb(DEB_OPEN, 'findDatafileBackup_c');
   OPEN findDatafileBackup_c(sourcemask         => imageCopy_con_t,
                             fno                => file#,
                             crescn             => creationSCN,
                             reset_scn          => reset_scn,
                             reset_time         => reset_time,
                             tag                => tag,
                             pattern            => file_name_pattern,
                             completedAfter     => completedAfter,
                             completedBefore    => completedBefore,
                             statusMask         => statusMask);
   deb(DEB_EXIT);
END listTranslateDataFileCopy;
----------------------------- listGetDataFileCopy -----------------------------
PROCEDURE listGetDataFileCopy(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'listGetDataFileCopy');
   FETCH findDatafileBackup_c
    INTO rcvRec;
   IF (findDatafileBackup_c%NOTFOUND) THEN
      CLOSE findDatafileBackup_c;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   -- Do not need to check the allocated device types.  Copies are available
   -- only on type DISK, so we can assume we wouldn't even be here if
   -- a DISK wasn't allocated.
   deb(DEB_EXIT);
END listGetDatafileCopy;
-- Obsolete as of 8.1.6
----------------------------- listGetDataFileCopy -----------------------------
FUNCTION listGetDataFileCopy(
   cdf_key            OUT number
  ,status             OUT varchar2
  ,fname              OUT varchar2
  ,completion_time    OUT date
  ,checkpoint_change# OUT number
  ,checkpoint_time    OUT date)
RETURN number IS
   rcvRec             rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'listGetDataFileCopy815');
   listGetDatafileCopy(rcvRec);
   cdf_key            := rcvRec.key_con;
   status             := rcvRec.status_con;
   fname              := rcvRec.fileName_con;
   completion_time    := rcvRec.compTime_con;
   checkpoint_change# := rcvRec.toSCN_act;
   checkpoint_time    := rcvRec.toTime_act;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
END listGetDataFileCopy;
------------------------- listTranslateArchivedLogCopy ------------------------
PROCEDURE listTranslateArchivedLogCopy(
   thread#           IN number
  ,sequence#         IN number
  ,first_change#     IN number
  ,file_name_pattern IN varchar2        DEFAULT NULL
  ,completedAfter    IN date            DEFAULT NULL
  ,completedBefore   IN date            DEFAULT NULL
  ,statusMask        IN binary_integer  DEFAULT
                       BSavailable+BSunavailable+BSexpired  -- 8.0/8.1 defaults
  ,needstby          IN number          DEFAULT NULL)
IS
   currentIncarnation number;
BEGIN
   deb(DEB_ENTER, 'listTranslateArchivedLogCopy');
   IF (allIncarnations = TRUE#) THEN
      currentIncarnation := FALSE#;             -- don't care about dbinc_key
   ELSE
      currentIncarnation := TRUE#;
   END IF;
   deb(DEB_OPEN, 'findArchivedLogCopy');
   OPEN findArchivedLogCopy(currentIncarnation => currentIncarnation,
                            thread             => thread#,
                            sequence           => sequence#,
                            lowSCN             => first_change#,
                            pattern            => file_name_pattern,
                            completedAfter     => completedAfter,
                            completedBefore    => completedBefore,
                            statusMask         => statusMask,
                            needstby           => needstby);
   deb(DEB_EXIT);
END listTranslateArchivedLogCopy;
---------------------------- listGetArchivedLogCopy ---------------------------
PROCEDURE listGetArchivedLogCopy(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'listGetArchivedLogCopy');
   -- Check if disk device is allocated.  Copies are available
   -- only on type DISK and no tag is associated with archivelog copies.
   -- If any of these conditions are not satisfied - then no archivelogs
   IF (restoreTag is not NULL OR
       not diskDevice)            THEN
      CLOSE findArchivedLogCopy;
      deb(DEB_EXIT, 'tag specified or no diskDevice allocated');
      RAISE no_data_found;
   END IF;
   FETCH findArchivedLogCopy
    INTO rcvRec;
   IF (findArchivedLogCopy%NOTFOUND) THEN
      CLOSE findArchivedLogCopy;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   deb(DEB_EXIT);
END listGetArchivedLogCopy;
-- Obsolete as of 8.1.6
---------------------------- listGetArchivedLogCopy ---------------------------
FUNCTION listGetArchivedLogCopy(
   al_key          OUT number
  ,status          OUT varchar2
  ,fname           OUT varchar2
  ,completion_time OUT date)
RETURN number IS
   rcvRec          rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'listGetArchivedLogCopy');
   listGetArchivedLogCopy(rcvRec);
   al_key          := rcvRec.key_con;
   status          := rcvRec.status_con;
   fname           := rcvRec.fileName_con;
   completion_time := rcvRec.compTime_con;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
END listGetArchivedLogCopy;
-----------------
-- List Backup --
-----------------
------------------------ listTranslateControlfileBackup -----------------------
PROCEDURE listTranslateControlfileBackup(
   tag             IN  varchar2
  ,completedAfter  IN  date
  ,completedBefore IN  date
  ,statusMask      IN  binary_integer   DEFAULT
                      BSavailable+BSunavailable+BSexpired   -- 8.0/8.1 defaults
  ,autobackup      IN  binary_integer   DEFAULT BScfile_all)
IS
BEGIN
   deb(DEB_ENTER, 'listTranslateControlfileBackup');
   IF (findControlfileBackup_c%ISOPEN) THEN     -- should not be open
      CLOSE findControlfileBackup_c;
   END IF;
   -- Replaces the lbcf cursor.  Note that the tag is handled by
   -- validateBackupSet in the get() procedure.
   deb(DEB_OPEN, 'findControlfileBackup_c');
   OPEN findControlfileBackup_c(-- ### This is probably a bug.
                                -- currentIncarnation should probably be true,
                                -- as it is for listTranslateControlfileCopy
                                currentIncarnation => FALSE#,
                                completedAfter     => completedAfter,
                                completedBefore    => completedBefore,
                                typemask           => autobackup);
   -- The following parameters are saved in global variables for use by
   -- the pre-8.1.6 listGetControlfileBackup procedure.  Note that the 8.1.6
   -- procedure does NOT use them.  Instead, it is expected that the 8.1.6
   -- RMAN will use the findValidBackupSet procedures to get a list of the
   -- valid copies of a backup set.
   listGetBackupTag           := tag;
   listGetBackupAvailableMask := statusMask;
   deb(DEB_EXIT);
END listTranslateControlfileBackup;
--------------------------- listGetControlfileBackup --------------------------
PROCEDURE listGetControlfileBackup(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'listGetControlfileBackup');
   FETCH findControlfileBackup_c
    INTO rcvRec;
   -- Note: no backupset validation done here.  RMAN should use the
   -- findValidBackupSet procedures to do that.
   IF (findControlfileBackup_c%NOTFOUND) THEN
      CLOSE findControlfileBackup_c;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   deb(DEB_EXIT);
END listGetControlfileBackup;
-- Obsolete as of 8.1.6
--------------------------- listGetControlfileBackup --------------------------
FUNCTION listGetControlfileBackup(
   bskey      OUT number,
   ckpscn     OUT number,
   ckptime    OUT date)
RETURN number IS
   rcvRec               rcvRec_t;
   validationRec        validBackupSetRec_t;
   validationRC         binary_integer;
BEGIN
   deb(DEB_ENTER, 'listGetControlfileBackup815');
   <<nextRow>>
   BEGIN
      listGetControlfileBackup(rcvRec);
   EXCEPTION
      WHEN no_data_found THEN
         deb(DEB_EXIT, 'with: FALSE#');
         RETURN FALSE#;
   END;
   validationRC :=
      validateBackupSet(backupSetRec           => rcvRec,
                        tag                    => listGetBackupTag,
                        tagMatchRequired       => TRUE,
                        checkDeviceIsAllocated => TRUE,
                        availableMask          => listGetBackupAvailableMask,
                        validRec               => validationRec);
   IF (validationRC <> SUCCESS) THEN
      GOTO nextRow;
   END IF;
   bskey      := rcvRec.bsKey_con;
   ckpscn     := rcvRec.toSCN_act;
   ckptime    := rcvRec.toTime_act;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
EXCEPTION
    WHEN no_data_found THEN
       deb(DEB_EXIT, 'with: FALSE#');
       RETURN FALSE#;
END listGetControlfileBackup;
------------------------ listTranslateSpfileBackup ---------------------------
PROCEDURE listTranslateSpfileBackup(
   completedAfter  IN  date
  ,completedBefore IN  date)
IS
BEGIN
   deb(DEB_ENTER, 'listTranslateSpfileBackup');
   IF (findSpfileBackup_c%ISOPEN) THEN                   -- should not be open
      CLOSE findSpfileBackup_c;
   END IF;
   deb(DEB_OPEN, 'findControlfileBackup_c');
   OPEN findSpfileBackup_c(completedAfter     => completedAfter,
                           completedBefore    => completedBefore);
   deb(DEB_EXIT);
END listTranslateSpfileBackup;
--------------------------- listGetSpfileBackup ------------------------------
PROCEDURE listGetSpfileBackup(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'listGetSpfileBackup');
   FETCH findSpfileBackup_c
    INTO rcvRec;
   -- Note: no backupset validation done here. RMAN should use the
   -- findValidBackupSet procedures to do that.
   IF (findSpfileBackup_c%NOTFOUND) THEN
      CLOSE findSpfileBackup_c;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   deb(DEB_EXIT);
END listGetSpfileBackup;
------------------------- listTranslateDataFileBackup -------------------------
PROCEDURE listTranslateDataFileBackup(
   file#             IN number
  ,creation_change#  IN number
  ,tag               IN varchar2        DEFAULT NULL
  ,completedAfter    IN date            DEFAULT NULL
  ,completedBefore   IN date            DEFAULT NULL
  ,statusMask        IN binary_integer  DEFAULT
                      BSavailable+BSunavailable+BSexpired)  -- 8.0/8.1 defaults
IS
   rlgSCN       number;
   rlgTime      date;
   crescn       number;
BEGIN
   deb(DEB_ENTER, 'listTranslateDataFileBackup');
   IF (findDatafileBackup_c%ISOPEN) THEN
      CLOSE findDatafileBackup_c;
   END IF;
   IF (allIncarnations = TRUE#) THEN
      IF (ignoreCreationSCN = TRUE#) THEN
         -- Since the flag is true, we want to list copies of all
         -- incarnations of each datafile number.  Set crescn to NULL so that
         -- the query returns all datafilecopies of a particular file#.
         -- This is used only by RMAN 8.1.5 and prior 8.1 releases.
         -- Leave rlgSCN and Time be null.
         crescn := NULL;
      ELSE
         crescn := creation_change#;
      END IF;
   ELSE
      -- The 8.0 RMAN did not list backups that belonged to incarnations
      -- other than the current incarnation.
      rlgSCN  := this_reset_scn;
      rlgTime := this_reset_time;
      crescn  := creation_change#;
   END IF;
   -- Replaces lbdf
   deb(DEB_OPEN, 'findDatafileBackup_c');
   OPEN findDatafileBackup_c(sourceMask         => backupSet_con_t,
                             fno                => file#,
                             crescn             => crescn,
                             reset_scn          => rlgSCN,
                             reset_time         => rlgTime,
                             completedAfter     => completedAfter,
                             completedBefore    => completedBefore);
   -- The following parameters are saved in global variables for use by
   -- the pre-8.1.6 listGetDatafileBackup procedure.  Note that the 8.1.6
   -- procedure does NOT use them.  Instead, it is expected that the 8.1.6
   -- RMAN will use the findValidBackupSet procedures to get a list of the
   -- valid copies of a backup set.
   listGetBackupTag           := tag;
   listGetBackupAvailableMask := statusMask;
   deb(DEB_EXIT);
END listTranslateDataFileBackup;
---------------------------- listGetDataFileBackup ----------------------------
PROCEDURE listGetDataFileBackup(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'listGetDataFileBackup');
   FETCH findDatafileBackup_c
    INTO rcvRec;
   IF (findDatafileBackup_c%NOTFOUND) THEN
      CLOSE findDatafileBackup_c;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   deb(DEB_EXIT);
END listGetDataFileBackup;
-- Obsolete as of 8.1.6
---------------------------- listGetDataFileBackup ----------------------------
FUNCTION listGetDataFileBackup(
   bs_key             OUT number
  ,backup_type        OUT varchar2
  ,incremental_level  OUT number
  ,completion_time    OUT date
  ,checkpoint_change# OUT number
  ,checkpoint_time    OUT date)
RETURN number IS
   rcvRec             rcvRec_t;
   valRC              binary_integer;
   validationRec      validBackupSetRec_t;
BEGIN
   deb(DEB_ENTER, 'listGetDataFileBackup815');
<<nextRow>>
   BEGIN
      listGetDataFileBackup(rcvRec => rcvRec);
   EXCEPTION
      WHEN no_data_found THEN
         deb(DEB_EXIT, 'with: FALSE#');
         RETURN FALSE#;
   END;
   valRC :=
      validateBackupSet(backupSetRec           => rcvRec,
                        tag                    => listGetBackupTag,
                        tagMatchRequired       => TRUE,
                        checkDeviceIsAllocated => TRUE,
                        availableMask          => listGetBackupAvailableMask,
                        validRec               => validationRec);
   IF (valRC <> SUCCESS) THEN
      GOTO nextRow;
   END IF;
   bs_key             := rcvRec.bsKey_con;
   IF (rcvRec.fromSCN_act = 0) THEN
      backup_type := 'Full';
   ELSE
      backup_type := 'Incremental';
   END IF;
   incremental_level  := rcvRec.level_act;
   completion_time    := rcvRec.compTime_con;           -- somewhat bogus
   checkpoint_change# := rcvRec.toSCN_act;
   checkpoint_time    := rcvRec.toTime_act;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
END listGetDataFileBackup;
-- A stupid idea from the 8.1 LIST implementation
----------------------------- translateBackupFile -----------------------------
PROCEDURE translateBackupFile(
   bs_recid    IN  number
  ,bs_stamp    IN  number
  ,fno         IN  number
  ,bskey       OUT number
  ,inclevel    OUT number
  ,backup_type OUT varchar2
  ,completed   OUT date)
IS
BEGIN
   deb(DEB_ENTER, 'translateBackupFile');
   -- Rather than running another query to get values we already
   -- fetched, we simply save the last rcvRec we fetched in a global
   -- variable.  We validate that the record matches
   -- our input args, and then simply extract the values and return them.
   -- The 8.1 implementation of LIST should have simply extended those other
   -- functions to return the values that it required rather than executing
   -- a 2nd query to fetch them, but that did not happen.
   IF (rcvRec_last.type_con <> backupSet_con_t OR
       rcvRec_last.bsRecid_con <> bs_recid OR
       rcvRec_last.bsStamp_con <> bs_stamp) THEN
      deb(DEB_EXIT, 'with error 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
   bskey     := rcvRec_last.bsKey_con;
   inclevel  := rcvRec_last.level_act;
   completed := rcvRec_last.compTime_con;
   IF (rcvRec_last.logSequence_obj IS NOT NULL) THEN
      backup_type := 'Archived Log';
   ELSE
      IF (rcvRec_last.fromSCN_act = 0) THEN
         backup_type := 'Full';
      ELSE
         backup_type := 'Incremental';
      END IF;
   END IF;
   deb(DEB_EXIT);
END translateBackupFile;
-- Used by 8.0 and 8.1.6, but not 8.1
------------------------ listTranslateArchivedLogBackup -----------------------
PROCEDURE listTranslateArchivedLogBackup(
   thread#              IN number
  ,sequence#            IN number
  ,first_change#        IN number
  ,completedAfter       IN date           DEFAULT NULL
  ,completedBefore      IN date           DEFAULT NULL
  ,statusMask           IN binary_integer DEFAULT
                      BSavailable+BSunavailable+BSexpired)  -- 8.0/8.1 defaults
IS
   currentInc number;
BEGIN
   deb(DEB_ENTER, 'listTranslateArchivedLogBackup');
   IF (allIncarnations = TRUE#) THEN
      currentInc := FALSE#;                      -- don't care about dbinc_key
   ELSE
      currentInc := TRUE#;
   END IF;
   deb(DEB_OPEN, 'findArcLogBackup');
   OPEN findArcLogBackup(currentIncarnation => currentInc,
                         thread             => thread#,
                         sequence           => sequence#,
                         lowSCN             => first_change#,
                         completedAfter     => completedAfter,
                         completedBefore    => completedBefore);
   listGetBackupAvailableMask := statusMask;
   deb(DEB_EXIT);
END listTranslateArchivedLogBackup;
--------------------------- listGetArchivedLogBackup --------------------------
PROCEDURE listGetArchivedLogBackup(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'listGetArchivedLogBackup');
   FETCH findArcLogBackup
    INTO rcvRec;
   IF (findArcLogBackup%NOTFOUND) THEN
      CLOSE findArcLogBackup;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   deb(DEB_EXIT);
END listGetArchivedLogBackup;
-- Obsolete as of 8.1
--------------------------- listGetArchivedLogBackup --------------------------
FUNCTION listGetArchivedLogBackup(
   bs_key          OUT number
  ,completion_time OUT date)
RETURN number IS
   rcvRec       rcvRec_t;
   validRec     validBackupSetRec_t;
   valRC        binary_integer;
BEGIN
   deb(DEB_ENTER, 'listGetArchivedLogBackup');
<<get_next>>
   listGetArchivedLogBackup(rcvRec);
   valRC :=
      validateBackupSet(backupSetRec           => rcvRec,
                        checkDeviceIsAllocated => TRUE,
                        availableMask          => listGetBackupAvailableMask,
                        validRec               => validRec);
   IF (valRC <> SUCCESS) THEN
      GOTO get_next;
   END IF;
   bs_key          := rcvRec.bsKey_con;
   completion_time := rcvRec.compTime_con;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
END listGetArchivedLogBackup;
-- Obsolete as of 8.1.6.
-- This  procedure is just a bad idea left here for backwards compatibility
-- with the broken LIST BACKUP OF ARCHIVELOG command of 8.1.
------------------------ listTranslateArchivedLogBackup -----------------------
PROCEDURE listTranslateArchivedLogBackup(
   thread#      IN number   DEFAULT NULL
  ,lowseq       IN number   DEFAULT NULL
  ,highseq      IN number   DEFAULT NULL
  ,lowscn       IN number   DEFAULT NULL
  ,highscn      IN number   DEFAULT NULL
  ,from_time    IN date     DEFAULT NULL
  ,until_time   IN date     DEFAULT NULL
  ,pattern      IN varchar2 DEFAULT NULL)
IS
BEGIN
   deb(DEB_ENTER, 'listTranslateArchivedLogBackup815');
   if lbal2%isopen then
      close lbal2;
   end if;
   deb(DEB_OPEN, 'lbal2');
   open lbal2(thread#, lowseq, highseq, lowscn, highscn, from_time, until_time);
   deb(DEB_EXIT);
END listTranslateArchivedLogBackup;
-- Obsolete as of 8.1.6
--------------------------- listGetArchivedLogBackup --------------------------
FUNCTION listGetArchivedLogBackup(
   bs_key          OUT number
  ,thread#         OUT number
  ,sequence#       OUT number
  ,first_change#   OUT number
  ,next_change#    OUT number
  ,first_time      OUT date
  ,next_time       OUT date)
RETURN number IS
   rcvRec          rcvRec_t;
   validRec        validBackupSetRec_t;
BEGIN
   deb(DEB_ENTER, 'listGetArchivedLogBackup815');
<<get_next>>
  fetch lbal2 into rcvRec;
  if lbal2%found then
    deb(DEB_PRINT, 'listGetArchivedLogBackup: got a backupset:');
    printRcvRec(rcvRec);
    if validateBackupSet(backupSetRec           => rcvRec,
                         checkDeviceIsAllocated => TRUE,
                         availableMask          => dbms_rcvman.BSavailable +
                                                   dbms_rcvman.BSunavailable +
                                                   dbms_rcvman.BSexpired,
                         validRec               => validRec) <> SUCCESS then
       goto get_next;
    end if;
    bs_key          := rcvRec.bsKey_con;
    thread#         := rcvRec.logThread_obj;
    sequence#       := rcvRec.logSequence_obj;
    first_change#   := rcvRec.logLowSCN_obj;
    next_change#    := rcvRec.logNextSCN_obj;
    first_time      := rcvRec.logLowTime_obj;
    next_time       := rcvRec.logNextTime_obj;
    deb(DEB_EXIT, 'with: TRUE#');
    RETURN TRUE#;
  else
    close lbal2;
    deb(DEB_EXIT, 'with: FALSE#');
    RETURN FALSE#;
  end if;
END listGetArchivedLogBackup;
--------------------
-- List Backupset --
--------------------
PROCEDURE listTranslateBackupsetFiles(
   bs_key          IN  number)
IS
BEGIN
   IF findBackupsetFiles%ISOPEN THEN
      CLOSE findBackupsetFiles;
   END IF;
   OPEN findBackupsetFiles(bs_key);
END;
PROCEDURE listGetBackupsetFiles(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   FETCH findBackupsetFiles
    INTO rcvRec;
   IF (findBackupsetFiles%NOTFOUND) THEN
      CLOSE findBackupsetFiles;
      RAISE no_data_found;
   END IF;
END;
------------------------
-- List All BackupSet --
------------------------
PROCEDURE translateAllBackupSet(
   backupType            IN  binary_integer
  ,tag                   IN  varchar2
  ,statusMask            IN  binary_integer
  ,completedAfter        IN  date
  ,completedBefore       IN  date)
IS
BEGIN
   IF findAllBackupPiece%ISOPEN THEN
      CLOSE findAllBackupPiece;
   END IF;
   OPEN findAllBackupPiece(backupType, tag, statusMask,
                           completedAfter, completedBefore);
END;
PROCEDURE getAllBackupSet(
   rcvRec OUT rcvRec_t)
IS
BEGIN
   FETCH findAllBackupPiece
    INTO rcvRec;
   IF (findAllBackupPiece%NOTFOUND) THEN
      CLOSE findAllBackupPiece;
      RAISE no_data_found;
   END IF;
END;
---------------------
-- List Proxy Copy --
---------------------
-- Note that this is used for both datafiles and the controlfile
-------------------------- listTranslateProxyDataFile -------------------------
PROCEDURE listTranslateProxyDataFile(
   file#             IN number
  ,creation_change#  IN number
  ,tag               IN varchar2        DEFAULT NULL
  ,handle_pattern    IN varchar2        DEFAULT NULL
  ,completedAfter    IN date            DEFAULT NULL
  ,completedBefore   IN date            DEFAULT NULL
  ,statusMask        IN binary_integer  DEFAULT BSavailable+BSunavailable+BSexpired)
                                                             -- default for 8.1
IS
   currentInc   number;
   crescn       number;
   reset_scn    number := NULL;
   reset_time   date   := NULL;
BEGIN
   deb(DEB_ENTER, 'listTranslateProxyDataFile');
   validateState(null);
   IF (allIncarnations = TRUE#) THEN
      currentInc := FALSE#;                     -- don't care about dbinc_key
      IF (ignoreCreationSCN = TRUE#) THEN
         -- Since the flag is true, we want to list copies of all
         -- incarnations of each datafile number.  Set crescn to NULL so that
         -- the query returns all datafilecopies of a particular file#.
         -- This is used only by RMAN 8.1.5 and prior 8.1 releases.
         crescn := NULL;
      ELSE
         crescn := creation_change#;
      END IF;
   ELSE
      currentInc := TRUE#;
      crescn     := creation_change#;
   END IF;
   IF (currentInc = TRUE#) THEN
      reset_scn  := this_reset_scn;
      reset_time := this_reset_time;
   END IF;
   IF (file# = 0) THEN
      IF (findControlfileProxyCopy%ISOPEN) THEN
         CLOSE findControlfileProxyCopy;
      END IF;
      -- This replaces lxdf
      deb(DEB_OPEN, 'findControlfileProxyCopy');
      OPEN findControlfileProxyCopy(currentIncarnation => currentInc,
                                    tag                => tag,
                                    pattern            => handle_pattern,
                                    completedAfter     => completedAfter,
                                    completedBefore    => completedBefore,
                                    statusMask         => statusMask);
      listGetProxyDatafileCursor := 'findControlfileProxyCopy';
   ELSE
      IF (findDatafileBackup_c%ISOPEN) THEN
         CLOSE findDatafileBackup_c;
      END IF;
      -- This replaces lxdf
      OPEN findDatafileBackup_c(sourcemask         => proxyCopy_con_t,
                                fno                => file#,
                                crescn             => crescn,
                                reset_scn          => reset_scn,
                                reset_time         => reset_time,
                                tag                => tag,
                                pattern            => handle_pattern,
                                completedAfter     => completedAfter,
                                completedBefore    => completedBefore,
                                statusMask         => statusMask);
      listGetProxyDatafileCursor := 'findDatafileBackup_c';
   END IF;
   deb(DEB_EXIT);
END listTranslateProxyDataFile;
----------------------------- listGetProxyDataFile ----------------------------
PROCEDURE listGetProxyDataFile(
   rcvRec OUT rcvRec_t)
IS
   local rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'listGetProxyDataFile');
<<nextRow>>
   IF (listGetProxyDatafileCursor = 'findControlfileProxyCopy') THEN
      FETCH findControlfileProxyCopy
       INTO local;
      IF (findControlfileProxyCopy%NOTFOUND) THEN
         CLOSE findControlfileProxyCopy;
         deb(DEB_EXIT, 'with no more records');
         RAISE no_data_found;
      END IF;
   ELSIF (listGetProxyDatafileCursor = 'findDatafileBackup_c') THEN
      FETCH findDatafileBackup_c
       INTO local;
      IF (findDatafileBackup_c%NOTFOUND) THEN
         CLOSE findDatafileBackup_c;
         deb(DEB_EXIT, 'with no more records');
         RAISE no_data_found;
      END IF;
   ELSE
      deb(DEB_EXIT, 'with error 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
   -- Proxy copies can be on different device types, so make sure we
   -- have the right one allocated.
   IF (isDeviceTypeAllocated(local.deviceType_con) = FALSE#) THEN
      GOTO nextRow;
   END IF;
   rcvRec := local;                             -- set OUT mode arg
   deb(DEB_EXIT);
END listGetProxyDataFile;
-- Obsolete as of 8.1.6
----------------------------- listGetProxyDataFile ----------------------------
FUNCTION listGetProxyDataFile(
   xdf_key            OUT number
  ,recid              OUT number
  ,stamp              OUT number
  ,status             OUT varchar2
  ,handle             OUT varchar2
  ,completion_time    OUT date
  ,checkpoint_change# OUT number
  ,checkpoint_time    OUT date)
RETURN number IS
   rcvRec             rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'listGetProxyDataFile815');
   listGetProxyDataFile(rcvRec);
   xdf_key              := rcvRec.key_con;
   recid                := rcvRec.recid_con;
   stamp                := rcvRec.stamp_con;
   status               := rcvRec.status_con;
   handle               := rcvRec.fileName_con;
   completion_time      := rcvRec.compTime_con;
   checkpoint_change#   := rcvRec.toSCN_act;
   checkpoint_time      := rcvRec.toTime_act;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
END listGetProxyDataFile;
-- This procedure serves absolutely no purpose.  It is here only for
-- backwards compatbility with 8.1.5.  The only call to this is from
-- krmkafs(), which gets called from krmkgra().  Since the calls are always
-- in sequence, we can simply save the last record returned from
-- getRecoveryAction and avoid doing an extra query.
-- The only value this functions returns that krmkgra() didn't already have
-- in 8.1.5 is the xdf_key.  Completion time was being estimated from the
-- stamp.
-------------------------- listTranslateProxyDFRecid --------------------------
PROCEDURE listTranslateProxyDFRecid(
   recid              IN number
  ,stamp              IN number
  ,xdf_key            OUT number
  ,file#              OUT number
  ,status             OUT varchar2
  ,handle             OUT varchar2
  ,completion_time    OUT date
  ,checkpoint_change# OUT number
  ,checkpoint_time    OUT date)
IS
BEGIN
   deb(DEB_ENTER, 'listTranslateProxyDFRecid');
   -- See if the last rcvRec we returned matches the one requested here.
   -- I think it will always be the case that we can use the value we
   -- saved in rcvRec_last.  But in case there is a path through Don's
   -- spaghetti code that I could not find, I include the cursor from the
   -- 8.1 package below and use it if the cached value is no good.
   IF (recid <> rcvRec_last.recid_con OR
       stamp <> rcvRec_last.stamp_con) THEN
  select d.xdf_key, d.file#, d.status, d.handle, d.completion_time,
         d.checkpoint_change#, d.checkpoint_time
  into xdf_key, file#, status, handle, completion_time, checkpoint_change#,
       checkpoint_time
  from   rc_proxy_datafile d
  where  db_key = this_db_key
  and   d.recid = listTranslateProxyDFRecid.recid
  and   d.stamp = listTranslateProxyDFRecid.stamp
  union all
  select c.xcf_key, 0, c.status, c.handle, c.completion_time,
         c.checkpoint_change#, c.checkpoint_time
  from   rc_proxy_controlfile c
  where  db_key = this_db_key
  and   c.recid = listTranslateProxyDFRecid.recid
  and   c.stamp = listTranslateProxyDFRecid.stamp;
   ELSE
      deb(DEB_PRINT, 'listTranslateProxyDFRecid: using cached rcvRec_last');
      xdf_key            := rcvRec_last.key_con;
      file#              := rcvRec_last.dfNumber_obj;
      status             := rcvRec_last.status_con;
      handle             := rcvRec_last.fileName_con;
      completion_time    := rcvRec_last.compTime_con;
      checkpoint_change# := rcvRec_last.toSCN_act;
      checkpoint_time    := rcvRec_last.toTime_act;
   END IF;
   deb(DEB_EXIT);
END listTranslateProxyDFRecid;
-------------------------------
-- List Database Incarnation --
-------------------------------
-------------------------- listTranslateDBIncarnation -------------------------
PROCEDURE listTranslateDBIncarnation(
   db_name      IN varchar2 DEFAULT NULL)
IS
BEGIN
   deb(DEB_ENTER, 'listTranslateDBIncarnation');
   IF (ldbi%isopen) THEN
      CLOSE ldbi;
   END IF;
   deb(DEB_OPEN, 'ldbi');
   OPEN ldbi(db_name);
   deb(DEB_EXIT);
END listTranslateDBIncarnation;
----------------------------- listGetDBIncarnation ----------------------------
FUNCTION listGetDBIncarnation(
   db_key            OUT number
  ,dbinc_key         OUT number
  ,db_name           OUT varchar2
  ,db_id             OUT number
  ,current_inc       OUT varchar2
  ,resetlogs_change# OUT number
  ,resetlogs_time    OUT date)
RETURN number
IS
BEGIN
   deb(DEB_ENTER, 'listGetDBIncarnation');
   FETCH ldbi
    INTO db_key, dbinc_key, db_name, db_id, current_inc,
         resetlogs_change#, resetlogs_time;
   IF (ldbi%found) THEN
      deb(DEB_EXIT, 'with: TRUE#');
      RETURN TRUE#;
   ELSE
      CLOSE ldbi;
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
   END IF;
   deb(DEB_EXIT);
END listGetDBIncarnation;
--------------------------------------
-- List Rollback Segment Tablespace --
--------------------------------------
-------------------------- listRollbackSegTableSpace --------------------------
PROCEDURE listRollbackSegTableSpace
IS
BEGIN
   deb(DEB_ENTER, 'listRollbackSegTableSpace');
   IF (lrtbs%ISOPEN) THEN
      CLOSE lrtbs;
   END IF;
   deb(DEB_OPEN, 'lrtbs');
   OPEN lrtbs;
   deb(DEB_EXIT);
END listRollbackSegTableSpace;
------------------------------ listGetTableSpace ------------------------------
FUNCTION listGetTableSpace(
   ts#               OUT number
  ,ts_name           OUT varchar2)
RETURN number
IS
BEGIN
   deb(DEB_ENTER, 'listGetTableSpace');
   FETCH lrtbs
    INTO ts#, ts_name;
   IF (lrtbs%FOUND) THEN
      deb(DEB_EXIT, 'with: TRUE#');
      RETURN TRUE#;
   ELSE
      CLOSE lrtbs;
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
   END IF;
   deb(DEB_EXIT);
END listGetTableSpace;
------------------------
-- Incremental Backup --
------------------------
------------------------------ getIncrementalScn ------------------------------
PROCEDURE getIncrementalScn(
   first        IN  boolean                  -- open the cursor if this is TRUE
  ,file#        IN  number
  ,create_scn   IN  number
  ,reset_scn    IN  number
  ,reset_time   IN  date
  ,incr_level   IN  number
  ,cumulative   IN  number
  ,rcvRec       OUT rcvRec_t)
IS
   ilevel       number;
   statusMask   number := BSavailable;
   local        rcvRec_t;
   validRec     validBackupSetRec_t;
BEGIN
   deb(DEB_ENTER, 'getIncrementalScn');
   IF (incr_level not in (1,2,3,4) OR incr_level is NULL) THEN
      raise_application_error(-20270, 'invalid incremental level');
   END IF;
   IF (cumulative not in (0,1) OR cumulative is NULL) THEN
      raise_application_error(-20271, 'invalid cumulative option');
   END IF;
   -- Find the backup with highest checkpoint scn that
   -- o belongs to the incarnation of datafile
   -- o matches the given file#
   -- o is an incremental backup/copy at level N or less if non-cumulative or
   --   is an incremental backup/copy at level N-1 or less if cumulative
   -- o belongs to an available backup set if backup
   -- NOTE: Backups from ancestral incarnations are ignored, even if there is
   -- a spanning offline range.  Incremental backups cannot cross resetlogs
   -- boundaries.
   IF (cumulative = TRUE#) THEN
      ilevel := incr_level - 1;         -- Consider only higher level backups
   ELSE
      ilevel := incr_level;
   END IF;
   IF first THEN
      IF (findDatafileBackup_c%ISOPEN) THEN
         CLOSE findDatafileBackup_c;
      END IF;
      getDatafileBackupLast.type_con := NULL; -- clear the last backup record
--
-- UNCOMMENT the following when you want to test qukvalidateBackupSet
-- with inCoreBsRec data structures. We did this change in catalog too
-- because we could do complete testing. This is not needed in catalog
-- because we didn't see much performance benefit. More importantly, PLSQL
-- consumes more memory to push a record so that for around 1MB of records
-- we hit PLSQL-6500 error. This is not acceptable for catalog mode.
--
--      IF (file# IS NULL) THEN
--         -- No specific fileno was requested. So, this must be a large
--         -- query for more number of datafiles like database translation.
--         -- In nocatalog mode, the best performance is achieved by
--         -- having all backuppiece information in memory.
--         createinCorebsRecStack(
--                   backupType             => BSdatafile_full + BSdatafile_incr
--                  ,tag                    => NULL
--                  ,statusMask             => statusMask
--                  ,checkDeviceIsAllocated => FALSE
--                  ,completedAfter         => NULL
--                  ,completedBefore        => NULL);
--         validateBackupSet_method := 'qukvalidateBackupSet';
--      ELSE
--         validateBackupSet_method := 'validateBackupSet';
--      END IF;
        
      -- Just use the usual method in catalog mode
      validateBackupSet_method := 'validateBackupSet';
      -- null reset_scn and reset_time means current incarnation
      OPEN findDatafileBackup_c(sourcemask => to_number(NULL),
                                fno        => file#,
                                crescn     => create_scn,
                                reset_scn  => nvl(reset_scn, this_reset_scn),
                                reset_time => nvl(reset_time, this_reset_time),
                                level      => ilevel,
                                statusMask => statusMask);
   END IF;
   IF (NOT findDatafileBackup_c%ISOPEN) THEN
      raise_application_error(-20272, 'cannot take incremental backup');
   END IF;
   LOOP
   <<nextRow>>
      FETCH findDatafileBackup_c
       INTO local;
      IF (findDatafileBackup_c%NOTFOUND) THEN
         deb(DEB_PRINT, 'closing cursor');
         CLOSE findDatafileBackup_c;
         IF (file# is NOT NULL) THEN
            -- there were no backups available for this file
            deb(DEB_EXIT, 'with: cannot take incr backup');
            raise_application_error(-20272, 'cannot take incremental backup');
         ELSE
            deb(DEB_EXIT, 'with: no data found');
            raise no_data_found;        -- no more datafile backups
         END IF;
      END IF;
      IF (getDatafileBackupLast.type_con IS NOT NULL AND
          getDatafileBackupLast.dfNumber_obj = local.dfNumber_obj) THEN
        GOTO nextRow;    -- this is a duplicate of what we saw earlier
      END IF;
      IF (local.type_con = backupSet_con_t) THEN
         --
         -- If this is same as the last backupset we validated, then
         -- this must also succeed. Save that validation time.
         --
         IF (getDatafileBackupLast.type_con IS NULL                   OR
             getDatafileBackupLast.type_con     != backupSet_con_t    OR
             getDatafileBackupLast.setStamp_con != local.setStamp_con OR
             getDatafileBackupLast.setCount_con != local.setCount_con) THEN
            -- We have to check the validity of the backupset to
            -- base an incremental backup upon it.
            IF (validateBackupSet_method = 'qukvalidateBackupSet') THEN
               -- This is a large query. Optimize this from in-memory tables
               IF (NOT qukvalidateBackupSet(bsKey => local.bsKey_con)) THEN
                  GOTO nextRow; -- not a valid backupset
               END IF;
            ELSIF (validateBackupSet_method = 'validateBackupSet') THEN
               IF (validateBackupSet(backupSetRec           => local,
                                     checkDeviceIsAllocated => FALSE,
                                     availableMask          => statusMask,
                                     validRec               => validRec)
                   = dbms_rcvman.UNAVAILABLE) THEN
                  GOTO nextRow; -- can't create an incr based on unavail backup
               END IF;
            ELSE
               raise_application_error(-20204, 'Translation not started');
            END IF;
         END IF;
      END IF;
      getDatafileBackupLast := local;   -- remember the last record
      rcvRec := local;
      deb(DEB_EXIT, 'with: valid record ');
      EXIT;   -- valid record. Create Incremental based on this SCN
   END LOOP;
EXCEPTION
   WHEN others THEN
      deb(DEB_PRINT, 'caught an exception during getIncrementalScn');
      deb(DEB_EXIT, substr(sqlerrm, 1, 512));
      raise;
END getIncrementalScn;
------------------------------ getIncrementalScn ------------------------------
FUNCTION getIncrementalScn(
   file#        IN number
  ,create_scn   IN number
  ,reset_scn    IN number
  ,reset_time   IN date
  ,incr_level   IN number
  ,cumulative   IN number)
RETURN number IS
  rcvRec    rcvRec_t;
BEGIN
   getIncrementalScn(
      first        => TRUE
     ,file#        => file#
     ,create_scn   => create_scn
     ,reset_scn    => reset_scn
     ,reset_time   => reset_time
     ,incr_level   => incr_level
     ,cumulative   => cumulative
     ,rcvRec       => rcvRec);
   IF (findDatafileBackup_c%ISOPEN) THEN
      CLOSE findDatafileBackup_c; -- close the one opened in getIncrementalScn
   END IF;
   RETURN rcvRec.toSCN_act;
END getIncrementalScn;
--------------------
-- Offline Ranges --
--------------------
-- Find a controlfile copy that contains the given offline range
-- The checkpoint scn of the controlfile must be greater than or equal to
-- the online scn because the offline range record is inserted into the
-- controlfile when the file is onlined.  The controlfile creation time
-- must be equal to the cursor parameter.
-- Lastly, the min_offr_recid must be
-- less than or equal to the offline range recid to guarantee that record
-- has not been written over in the controlfile copy.
----------------------------- findOfflineRangeCopy ----------------------------
PROCEDURE findOfflineRangeCopy(
   offr_recid   IN number
  ,offr_ckpscn  IN number
  ,cf_cretime   IN date
  ,dbinc_key    IN number)
IS
BEGIN
   deb(DEB_ENTER, 'findOfflineRangeCopy');
   validateState(null);
   deb(DEB_OPEN, 'getOfflineRangeCopy_c');
   OPEN getOfflineRangeCopy_c(offrRecid  => offr_recid,
                              offrCkpSCN => offr_ckpscn,
                              cfCreTime  => cf_cretime,
                              dbincKey   => dbinc_key);
   deb(DEB_EXIT);
END findOfflineRangeCopy;
----------------------------- getOfflineRangeCopy -----------------------------
PROCEDURE getOfflineRangeCopy(
   rcvRec       OUT     rcvRec_t)
IS
BEGIN
   deb(DEB_ENTER, 'getOfflineRangeCopy');
   IF (NOT getOfflineRangeCopy_c%ISOPEN) THEN
      deb(DEB_EXIT, 'with error 20204');
      raise_application_error(-20204, 'Translation not started');
   END IF;
   FETCH getOfflineRangeCopy_c
    INTO rcvRec;
   IF (getOfflineRangeCopy_c%NOTFOUND) THEN
      CLOSE getOfflineRangeCopy_c;
      deb(DEB_EXIT, 'with no more records');
      RAISE no_data_found;
   END IF;
   CLOSE getOfflineRangeCopy_c;
   deb(DEB_EXIT);
END getOfflineRangeCopy;
-- Obsolete as of 8.1.6
----------------------------- getOfflineRangeCopy -----------------------------
FUNCTION getOfflineRangeCopy
RETURN varchar2 IS
   rcvRec       rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'getOfflineRangeCopy815');
   getOfflineRangeCopy(rcvRec);
   deb(DEB_EXIT, 'with: fileName');
   RETURN rcvRec.fileName_con;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with: NULL');
      RETURN NULL;
END getOfflineRangeCopy;
--------------------------------------
-- Recovery Functions and Procedures --
---------------------------------------
------------------------ setComputeRecoveryActionMasks ------------------------
PROCEDURE setComputeRecoveryActionMasks(
   containerMask        IN number
  ,actionMask           IN number
  ,allRecords           IN number
  ,availableMask        IN binary_integer)
IS
BEGIN
   deb(DEB_ENTER, 'setComputeRecoveryActionMasks');
   getRA_containerMask := containerMask;
   getRA_actionMask    := actionMask;
   computeRA_allRecords := allRecords;
   computeRA_availableMask := availableMask;
   deb(DEB_EXIT);
END setComputeRecoveryActionMasks;
-- Obsolete as of 8.1.7
------------------------ setComputeRecoveryActionMasks ------------------------
PROCEDURE setComputeRecoveryActionMasks(
   containerMask        IN number
  ,actionMask           IN number
  ,allRecords           IN number)
IS
BEGIN
   deb(DEB_ENTER, 'setComputeRecoveryActionMasks816');
   setComputeRecoveryActionMasks(
      containerMask => containerMask,
      actionMask    => actionMask,
      allRecords    => allRecords,
      availableMask => dbms_rcvman.BSavailable);
   deb(DEB_EXIT);
END setComputeRecoveryActionMasks;
-- Obsolete as of 8.1.6
---------------------------------- setRAflags ---------------------------------
PROCEDURE setRAflags(
   kindMask    IN number
  ,allRecords  IN boolean)
IS
   containerMask        number;
   actionMask           number;
   allRecs              number;
BEGIN
   deb(DEB_ENTER, 'setRAflags');
   -- Set container mask
   containerMask := 0;
   IF (bitand(kindMask, implicitOfflRange + cleanRange + applyOfflRange) > 0)
   THEN
      containerMask := containerMask + offlineRangeRec_con_t;
   END IF;
   IF (bitand(kindMask, dfCopy) > 0) THEN
      containerMask := containerMask + imageCopy_con_t;
   END IF;
   IF (bitand(kindMask, buSet + applyIncremental) > 0) THEN
      containerMask := containerMask + backupSet_con_t;
   END IF;
   IF (bitand(kindMask, proxyFull) > 0) THEN
      containerMask := containerMask + proxyCopy_con_t;
   END IF;
   -- Set Action Mask
   actionMask := 0;
   IF (bitand(kindMask, dfCopy + ProxyFull + buSet) > 0) THEN
      actionMask := actionMask + full_act_t;
   END IF;
   IF (bitand(kindMask, applyIncremental) > 0) THEN
      actionMask := actionMask + incremental_act_t;
   END IF;
   IF (bitand(kindMask, redo) > 0) THEN
      actionMask := actionMask + redo_act_t;
   END IF;
   IF (bitand(kindMask, implicitOfflRange) > 0) THEN
      actionMask := actionMask + implicitRange_act_t;
   END IF;
   IF (bitand(kindMask, cleanRange) > 0) THEN
      actionMask := actionMask + cleanRange_act_t;
   END IF;
   IF (bitand(kindMask, applyOfflRange) > 0) THEN
      actionMask := actionMask + offlineRange_act_t;
   END IF;
   IF (allRecords) THEN
      allRecs := TRUE#;
   ELSE
      allRecs := FALSE#;
   END IF;
   deb(DEB_PRINT, 'setRAflags kindMask=' || to_char(kindMask) ||
       ' containerMask=' || to_char(containerMask) ||
       ' actionMask=' || to_char(actionMask));
   setComputeRecoveryActionMasks(containerMask, actionMask, allRecs);
   deb(DEB_EXIT);
END setRAflags;
---------------------------- computeRecoveryActions ---------------------------
FUNCTION computeRecoveryActions(
fno        IN number,   -- Datafile number.
crescn     IN number,   -- Datafile creation SCN.
df_rlgscn  IN number    -- Datafile resetlogs SCN.  Null unless we are doing
   default null,        -- a RECOVER, in which case is the value in the
                        -- datafile header.
df_rlgtime IN date      -- Datafile resetlogs time.  Null if df_rlgscn is
   default null,        -- null, else value from datafile header.
df_ckpscn  IN number    -- Datafile checkpoint SCN.  Null if df_rlgscn is
   default null,        -- null, else value from datafile header.
offlscn    IN number    -- kccfeofs (0 -> no offline range)
   default 0,
onlscn     IN number    -- kccfeonc (0 if offlscn is 0).
   default 0,
onltime    IN date      -- kccfonc_time
   default null,
cleanscn   IN number    -- kccfecps if either SOR or WCC set, else 0.
   default 0,
clean2scn  IN number    -- CF ckpt SCN if WCC set, infinity if SOR bit set
   default 0,           -- else 0.
clean2time IN date      -- controlfile ckpt time if WCC, SYSDATE if SOR, else
   default null,        -- this is ignored if cleanscn is 0
allowfuzzy IN boolean   -- TRUE if can be fuzzy at until SCN/time, FALSE if
  default FALSE,        -- not.  default is FALSE.
partial_rcv IN boolean  -- TRUE if can do partial recovery, FALSE if not.
  default FALSE,        -- A partial recovery would be to recover a datafile
                        -- using redo up to some SCN, and then switching
                        -- back to incrementals.  This would be done
                        -- because of a missing/unavailable incremental backup.
                        -- We need to know because a partial
                        -- media recovery can only be done if we have a
                        -- current controlfile.  A partial recovery does not
                        -- recover the controlfile.  This could be implemented,
                        -- but it requires using an enqueue to ensure only
                        -- 1 process tries to recover the confile.
                        -- Since we aren't recovering the controlfile,
                        -- the file header won't be handled properly when
                        -- we hit controlfile redo.  That is why we are
                        -- requiring a current controlfile.
                        -- The default is false because RMAN currently does
                        -- not support partial recovery.
cf_scn     IN number    -- controlfile ckpt SCN (NULL if none mounted)
  default NULL,
cf_cretime IN date      -- controlfile creation time (NULL if none mounted)
  default NULL,
cf_offrrid IN number    -- recid of oldest offline range in controlfile
  default NULL,         -- (NULL if none mounted)
allCopies  IN boolean
  default FALSE)
RETURN binary_integer IS
   rc          boolean;
   last        number;
   this        number;
   succ_flag   boolean;
   thisAct     rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'computeRecoveryActions');
   IF (this_dbinc_key is NULL) THEN
      deb(DEB_EXIT, 'with error 20020');
      raise_application_error(-20020, 'Database incarnation not set');
   END IF;
   IF (rcvRecStack.count > 0) THEN
      rcvRecStack.trim(rcvRecStack.count);
   END IF;
   computeRA_restorable := FALSE;
   computeRA_available := FALSE;
   rcvRecStackState.lowAction := 0;
   rcvRecStackState.savePoint := 0;
   rcvRecStackState.top       := 0;
   IF (allCopies) THEN
      deb(DEB_IN, 'allCopies is TRUE');
   ELSE
      deb(DEB_IN, 'allCopies is FALSE');
   END IF;
   deb(DEB_IN, 'this_dbinc_key is:'||to_char(this_dbinc_key));
   rc := computeRecoveryActions(fno, crescn, df_rlgscn, df_rlgtime,
                                df_ckpscn,
                                offlscn, onlscn, onltime,
                                cleanscn, clean2scn, clean2time,
                                allowfuzzy, partial_rcv,
                                null, this_dbinc_key,
                                cf_scn, cf_cretime, cf_offrrid,
                                FALSE, succ_flag, allCopies);
   IF (succ_flag) THEN
      IF (rcvRecStack.count > 0) THEN
         IF (computeRA_allRecords = FALSE#) THEN
            -- We need to find any incremental backups that are redundant
            -- and mark them to be skipped.  It is possible that we
            -- have stacked an incremental backup that we can skip because
            -- it overlaps two other incremental backups.
            -- We can delete action n if action n - 1 can be applied on
            -- top of action n + 1.  I.e., if the toSCN(n+1) >= fromSCN(n-1).
            -- Note that the actions on the stack, from top..1, are in
            -- descending toSCN order.  This means n+1 comes before n-1.
            -- Loop from top-1..2  These are the "middle" actions.  Go in
            -- reverse order since that is the order in which the stack was
            -- built.  "last" is the last action we know we are keeping.
            -- We know we are keeping the action at the top of the stack, as it
            -- is always a full backup.  So "last" starts at the stack top.
            -- "last" is n+1 in the formula above.
            last := rcvRecStack.count;
            FOR this IN REVERSE 2..rcvRecStack.count - 1 LOOP
               IF ((rcvRecStack(last).toSCN_act >=
                    rcvRecStack(this-1).fromSCN_act) AND NOT
                   -- Keep it if allCopies and it is the same container.
                   (allCopies AND
                    rcvRecStack(this).key_con = rcvRecStack(this-1).key_con AND
                    rcvRecStack(this).type_con = rcvRecStack(this-1).type_con))
                  THEN
                  deb(DEB_PRINT, 'computeRecoveryActions: marking this action deleted:');
                  rcvRecGet(this, thisAct);
                  printRcvRec(thisAct);
                  rcvRecStack(this).type_con :=
                     rcvRecStack(this).type_con + deleted_con_t;
               ELSE
                  -- We are going to keep this action, so it becomes the last.
                  last := this;
               END IF;
            END LOOP;
         END IF;                -- computeRA_allRecords = FALSE#
         deb(DEB_EXIT, 'with: SUCCESS');
         RETURN SUCCESS;
      ELSE
         deb(DEB_EXIT, 'with: NO_ACTION');
         RETURN NO_ACTION;      -- a recovery that can only use redo
      END IF;
   ELSIF (computeRA_available) THEN
      deb(DEB_EXIT, 'with: AVAILABLE');
      RETURN dbms_rcvman.AVAILABLE;
   ELSIF (computeRA_restorable) THEN
      deb(DEB_EXIT, 'with: RESTORABLE');
      RETURN RESTORABLE;
   ELSE
      deb(DEB_EXIT, 'with: UNAVAILABLE');
      RETURN dbms_rcvman.UNAVAILABLE;
   END IF;
END computeRecoveryActions;
------------------------------ getRecoveryAction ------------------------------
FUNCTION getRecoveryAction(
   action OUT rcvRec_t)
RETURN binary_integer IS
   redoAction rcvRec_t;
   skip       boolean;
   local      rcvRec_t;
   top        rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'getRecoveryAction');
<<getNext>>
   IF (rcvRecStack.count = 0) THEN
      -- Signal to krmk we have reached the end.
      -- We usually only get here if filtering, in which case we cannot
      -- always predict when we have reached the last row.
      --
      -- pre-8.1.3 rman does not tell us to filter out any records (via
      -- the RA flags), so we should not get here.  If we do then it is
      -- a protocol error, so we really should signal an error.
      -- However, there is no way to signal an internal error from a
      -- package.  So just raise the no-data-found condition.
      -- This will cause the pre-8.1.3 RMAN to signal an error because
      -- it does not tolerate any errors from getRecoveryAction.
      deb(DEB_EXIT, 'with no more records');
      raise no_data_found;
   END IF;
   rcvRecPop(local);
   -- See if we want this action kind or not
   IF (bitand(local.type_con, getRA_containerMask) = 0) THEN
      deb(DEB_PRINT, 'getRecoveryAction: skipping non-selected container type');
      skip := TRUE;                             -- then skip this action
   ELSIF (bitand(local.type_act, getRA_actionMask) = 0) THEN
      deb(DEB_PRINT, 'getRecoveryAction: skipping non-selected action type');
      skip := TRUE;                             -- then skip this action
   ELSIF (bitand(local.type_con, deleted_con_t) > 0) THEN
      deb(DEB_PRINT, 'getRecoveryAction: deleted action skipped:');
      skip := TRUE;                             -- then skip this action
   -- If we were doing a LIST, compare the TAG if specified
   ELSIF (computeRA_allRecords = TRUE# AND
          restoreTag is not null AND
          bitand(local.type_con, tagMask_con_t) > 0 AND
          (local.tag_con <> restoreTag OR local.tag_con is null)) THEN
      deb(DEB_PRINT, 'getRecoveryAction: tag mismatch - skipped:');
      skip := TRUE;                             -- then skip this action
   -- Compare the COMPLETED AFTER time if specified.  Note that
   -- local.compTime may be null.
   ELSIF (getRA_completedAfter IS NOT NULL AND
          local.compTime_con < getRA_completedAfter) THEN
      deb(DEB_PRINT, 'getRecoveryAction: compTime < completedAfter - skipped:');
      skip := TRUE;                             -- then skip this action
   -- Compare the COMPLETED BEFORE if specified
   ELSIF (getRA_completedBefore IS NOT NULL AND
          local.compTime_con > getRA_completedBefore) THEN
      deb(DEB_PRINT, 'getRecoveryAction: compTime > completedBefore - skipped:');
      skip := TRUE;                             -- then skip this action
   -- Compare the LIKE pattern if specified
   ELSIF (getRA_likePattern IS NOT NULL AND
          local.fileName_con NOT LIKE getRA_likePattern) THEN
      deb(DEB_PRINT, 'getRecoveryAction: LikePattern not matched - skipped:');
      skip := TRUE;                             -- then skip this action
   ELSE
      skip := FALSE;
   END IF;
   IF (skip) THEN
      printRcvRec(local);
      GOTO getNext;
   END IF;
<<merge_actions>>
   IF (rcvRecStack.count > 0) THEN
      --------------------------------------------------------
      -- See if the next action can be merged with this one --
      --------------------------------------------------------
      rcvRecTop(top);
      IF (local.type_act = redo_act_t AND
          top.type_act = redo_act_t) THEN
         -- Two contiguous redo actions can always be merged.  We know they
         -- must be from the same incarnation because an offline range
         -- action always appears between 2 different incarnations.
         redoAction := local;
         rcvRecPop(local);
         local.fromSCN_act := redoAction.fromSCN_act;
         GOTO merge_actions;
      END IF;
      action := local;
      rcvRec_last := local;
      deb(DEB_EXIT, 'with: TRUE#');
      RETURN TRUE#;                     -- more actions to return yet
   ELSE
      action := local;
      rcvRec_last := local;
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;                    -- this is the last action
   END IF;
END getRecoveryAction;
-- Obsolete as of 8.1.6
------------------------------ getRecoveryAction ------------------------------
FUNCTION getRecoveryAction(
   kind       OUT number
  ,set_stamp  OUT number
  ,set_count  OUT number
  ,recid      OUT number
  ,stamp      OUT number
  ,fname      OUT varchar2
  ,blocksize  OUT number
  ,blocks     OUT number
  ,devtype    OUT varchar2
  ,from_scn   OUT number
  ,to_scn     OUT number
  ,to_time    OUT date
  ,rlgscn     OUT number
  ,rlgtime    OUT date
  ,cfcretime  OUT date
  ,dbinc_key  OUT number)
RETURN binary_integer IS
   rcvRec     rcvRec_t;
   rc         binary_integer;
BEGIN
   deb(DEB_ENTER, 'getRecoveryAction815');
   rc := getRecoveryAction(rcvRec);
   IF (rcvRec.type_con = offlineRangeRec_con_t) THEN
      IF (rcvRec.type_act = offlineRange_act_t) THEN
         kind := applyOfflRange;
      ELSIF (rcvRec.type_act = cleanRange_act_t) THEN
         kind := cleanRange;
      ELSIF (rcvRec.type_act = implicitRange_act_t) THEN
         kind := implicitOfflRange;
      ELSE
         deb(DEB_PRINT, 'cannot convert type_con=' || to_char(rcvRec.type_con) ||
             ' type_act=' || to_char(rcvRec.type_act) ||
             ' to recovery action kind');
         deb(DEB_EXIT, 'with error 20000');
         raise_application_error(-20000, 'internal error: getRecoveryAction');
      END IF;
   ELSIF (rcvRec.type_con = backupSet_con_t) THEN
      IF (rcvRec.type_act = full_act_t) THEN
         kind := buSet;
      ELSE
         kind := applyIncremental;
      END IF;
   ELSIF (rcvRec.type_con = proxyCopy_con_t) THEN
      kind := proxyFull;
   ELSIF (rcvRec.type_con = imageCopy_con_t) THEN
      kind := dfCopy;
   ELSIF (rcvRec.type_con IS NULL) THEN
      IF (rcvRec.type_act = redo_act_t) THEN
         kind := redo;
      END IF;
   END IF;
   deb(DEB_PRINT, 'getRecoveryAction: kind=' || nvl(to_char(kind), 'null'));
   rcvRecConvert(rcvRec);                       -- get rid of nulls
   printRcvRec(rcvRec);
   set_stamp := rcvRec.setStamp_con;
   set_count := rcvRec.setCount_con;
   IF (rcvRec.type_con = backupSet_con_t) THEN
      recid     := rcvRec.bsRecid_con;
      stamp     := rcvRec.bsStamp_con;
   ELSE
      recid     := rcvRec.recid_con;
      stamp     := rcvRec.stamp_con;
   END IF;
   fname     := rcvRec.fileName_con;
   blocksize := rcvRec.blockSize_con;
   blocks    := rcvRec.blocks_con;
   devtype   := rcvRec.deviceType_con;
   from_scn  := rcvRec.fromSCN_act;
   to_scn    := rcvRec.toSCN_act;
   to_time   := rcvRec.toTime_act;              -- null OK
   rlgscn    := rcvRec.rlgSCN_act;
   rlgtime   := rcvRec.rlgTime_act;
   cfcretime := rcvRec.cfCreationTime_con;      -- null OK
   dbinc_key := rcvRec.dbincKey_act;            -- null OK
   deb(DEB_EXIT, 'with: '||to_char(rc));
   RETURN rc;
END;
----------------------------- printRecoveryActions ----------------------------
PROCEDURE printRecoveryActions
IS
   action rcvRec_t;
   rc     number;
BEGIN
   deb(DEB_PRINT, '===== ' || to_char(rcvRecStack.count) || ' actions stacked =====');
   IF (rcvRecStack.count = 0) THEN
      return;
   END IF;
   LOOP
      rc := getRecoveryAction(action);
      printRcvRec(action);
      EXIT WHEN rc = FALSE#;
   END LOOP;
END printRecoveryActions;
----------------------------- trimRecoveryActions -----------------------------
PROCEDURE trimRecoveryActions(
   maxActions           IN number
  ,containerMask        IN number
  ,actionMask           IN number)
IS
   n                    number;
BEGIN
   deb(DEB_ENTER, 'trimRecoveryActions[procedure]');
   n := trimRecoveryActions(maxActions, containerMask, actionMask);
   deb(DEB_EXIT);
END trimRecoveryActions;
---------------------
-- Report Obsolete --
---------------------
----------------------------- reportTranslateDFDel ----------------------------
PROCEDURE reportTranslateDFDel
IS
BEGIN
   deb(DEB_ENTER, 'reportTranslateDFDel');
   IF (rddf%isopen) THEN
      CLOSE rddf;
   END IF;
   deb(DEB_OPEN, 'rddf');
   OPEN rddf;
   deb(DEB_EXIT);
END reportTranslateDFDel;
-- pre-8.1.5 version.  Discards unused out variables and PROXY rows.
-------------------------------- reportGetDFDel -------------------------------
FUNCTION reportGetDFDel(
   file#               OUT number
  ,filetype            OUT number
  ,checkpoint_change#  OUT number
  ,checkpoint_time     OUT date
  ,resetlogs_change#   OUT number
  ,resetlogs_time      OUT date
  ,incremental_change# OUT number
  ,fuzzy_change#       OUT number
  ,recid               OUT number
  ,stamp               OUT number
  ,fname               OUT varchar2
  ,restorable          OUT number)
RETURN number IS
   rc              number;
   mytype          number;
   key             number;
   completion_time date;
BEGIN
   deb(DEB_ENTER, 'reportGetDFDel80');
   <<get_next>>
   rc := reportGetDFDel( file#
                        ,mytype
                        ,checkpoint_change#
                        ,checkpoint_time
                        ,resetlogs_change#
                        ,resetlogs_time
                        ,incremental_change#
                        ,fuzzy_change#
                        ,recid
                        ,stamp
                        ,fname
                        ,restorable
                        ,key
                        ,completion_time);
   IF (rc = TRUE#) THEN
      IF (mytype = PROXY) THEN
         GOTO get_next;
      END IF;
      filetype := mytype;
   END IF;
   deb(DEB_EXIT, 'with: '||to_char(rc));
   RETURN rc;
END reportGetDFDel;
-- 8.1.5+ version
-------------------------------- reportGetDFDel -------------------------------
FUNCTION reportGetDFDel(
   file#               OUT number
  ,filetype            OUT number
  ,checkpoint_change#  OUT number
  ,checkpoint_time     OUT date
  ,resetlogs_change#   OUT number
  ,resetlogs_time      OUT date
  ,incremental_change# OUT number
  ,fuzzy_change#       OUT number
  ,recid               OUT number
  ,stamp               OUT number
  ,fname               OUT varchar2
  ,restorable          OUT number
  ,key                 OUT number
  ,completion_time     OUT date)
RETURN number IS
   device_type rc_backup_piece.device_type%TYPE;
   mytype      number;
   set_stamp   number;
   set_count   number;
   pref        number;
   bsRec       bsRec_t;
   validRec    validBackupSetRec_t;
   rcvRec      rcvRec_t;
BEGIN
   deb(DEB_ENTER, 'reportGetDFDel');
   FETCH rddf
    INTO pref, file#, mytype, checkpoint_change#, checkpoint_time,
         resetlogs_change#, resetlogs_time, incremental_change#, fuzzy_change#,
         recid, stamp, fname, set_stamp, set_count, key, completion_time,
         device_type;
   filetype := mytype;
   IF (rddf%found) THEN
      IF (mytype in (FULL_DF_BACKUP, INCREMENTAL_DF_BACKUP)) THEN
         findBackupSet(recid => recid,
                       stamp => stamp,
                       bsRec => bsRec);
         -- This is a bit dangerous.  We are hacking together a rcvRec
         -- from a bsRec.
         rcvRec.bsKey_con      := bsRec.key;
         rcvRec.elapseSecs_con := bsRec.elapseSecs;
         rcvRec.pieceCount_con := bsRec.pieceCount;
         restorable := validateBackupSet(
            backupSetRec           => rcvRec,
            checkDeviceIsAllocated => TRUE,
            availableMask          => dbms_rcvman.BSavailable,
            validRec               => validRec);
      ELSIF (mytype = OFFLINE_RANGE) THEN
         restorable := SUCCESS;
      ELSE
         IF (isDeviceTypeAllocated(device_type) = TRUE#) THEN
            restorable := SUCCESS;
         ELSE
            restorable := dbms_rcvman.AVAILABLE;
         END IF;
      END IF;
      deb(DEB_EXIT, 'with: '||TRUE#);
      RETURN TRUE#;
   ELSE
      CLOSE rddf;
      deb(DEB_EXIT, 'with: '||FALSE#);
      RETURN FALSE#;
   END IF;
END reportGetDFDel;
------------
-- TSPITR --
------------
--------------------------------- getCloneName --------------------------------
FUNCTION getCloneName(
   fno    IN number
  ,crescn IN number)
RETURN varchar2 IS
   fname df.clone_fname%TYPE;
BEGIN
   deb(DEB_ENTER, 'getCloneName');
   IF (this_dbinc_key is NULL) THEN
      deb(DEB_EXIT, 'with error 20020');
      raise_application_error(-20020, 'Database incarnation not set');
   END IF;
   SELECT clone_fname
     INTO fname
     FROM df
    WHERE dbinc_key = this_dbinc_key
      AND file# = fno
      AND create_scn = crescn;
   deb(DEB_EXIT, 'with: '||fname);
   RETURN fname;
EXCEPTION
   WHEN no_data_found THEN
      -- This should never happen.  The fno and crescn values came from
      -- the recovery catalog, so we should have this record.
      deb(DEB_EXIT, 'with error 20218');
      raise_application_error(-20218,
                              'Datafile not found in recovery catalog');
   WHEN others THEN
      deb(DEB_EXIT, 'Just raising error');
      raise;
END getCloneName;
---------------
-- DUPLICATE --
---------------
--------------------------------- wasFileOffline ------------------------------
FUNCTION wasFileOffline(
   fno    IN number
  ,untilscn IN number)
RETURN number IS
   x     number;
BEGIN
   deb(DEB_ENTER, 'wasFileOffline');
  select 1
    into x
    from rc_offline_range ofr, rc_database_incarnation di
   where ofr.db_key = this_db_key
     and di.db_key = this_db_key
     and ofr.dbinc_key = di.dbinc_key
     and untilscn >= offline_change#
     and untilscn < online_change#
     and file# = fno;
   deb(DEB_EXIT, 'with: TRUE#');
   RETURN TRUE#;
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT, 'with: FALSE#');
      RETURN FALSE#;
END wasFileOffline;
-------------------------
-- RMAN Configuration ---
-------------------------
-------------------------------- getConfig ------------------------------------
PROCEDURE getConfig(
   conf#         OUT    number
  ,name          IN OUT varchar2
  ,value         IN OUT varchar2
  ,first         IN     boolean)
IS
   eof          boolean := FALSE;
BEGIN
   IF (first) THEN
      IF (findConfig_c%ISOPEN) THEN
         CLOSE findConfig_c;
      END IF;
      OPEN findConfig_c(name, value);
   END IF;
   FETCH findConfig_c INTO conf#, name, value;
   IF (findConfig_c%NOTFOUND) THEN
      eof := TRUE;
      CLOSE findConfig_c;
   END IF;
   IF (eof) THEN                                --- if end of fetch
     RAISE no_data_found;
   END IF;
END getConfig;
----------------------------------
-- Get max(copy#) backup piece --
----------------------------------
--------------------------------- getmaxcopyno---------------------------------
FUNCTION getmaxcopyno(
   bsstamp         IN    number
  ,bscount         IN    number)
RETURN number IS
   maxcopy number;
BEGIN
   select max(copy#)
      into maxcopy
      from rc_backup_piece  bp
      where bp.set_stamp = bsstamp
      and   bp.set_count = bscount
      and   bp.db_key = this_db_key;
   return maxcopy;
END getmaxcopyno;
--------------------------------------
-- Add corruption table to BMR list --
--------------------------------------
----------------------------- bmraddcorrupttable-------------------------------
PROCEDURE bmrAddCorruptTable(
   dfnumber    OUT number
  ,blknumber   OUT number
  ,range       OUT number
  ,first       IN  boolean)
IS
   eof    boolean := FALSE;
BEGIN
   IF (first) THEN
      IF (bmrAddCorruptTable_c%ISOPEN) THEN
         CLOSE bmrAddCorruptTable_c;
      END IF;
      OPEN bmrAddCorruptTable_c;
   END IF;
   FETCH bmrAddCorruptTable_c INTO dfnumber, blknumber, range;
   IF (bmrAddCorruptTable_c%NOTFOUND) THEN
      eof := TRUE;
      CLOSE bmrAddCorruptTable_c;
   END IF;
   IF (eof) THEN                                --- if end of fetch
     RAISE no_data_found;
   END IF;
END;
--------getBackupHistory------------
-- Get Backup History Information --
------------------------------------
PROCEDURE getDfBackupHistory(
   backedUpDev     IN   varchar2
  ,first           IN   boolean
  ,file#           IN   number  DEFAULT NULL
  ,crescn          IN   number  DEFAULT NULL
  ,reset_scn       IN   number  DEFAULT NULL
  ,reset_time      IN   date    DEFAULT NULL
  ,bhistoryRec     OUT  bhistoryRec_t)
IS
   eof       boolean := FALSE;
   local     bhistoryRec_t;
   icount    number  := 0;
BEGIN
   deb(DEB_ENTER, 'getDfBackupHistory');
   IF (first) THEN
      getLastBackupHistory.key := NULL;
      IF (dfBackupHistory_c%ISOPEN) THEN
         CLOSE dfBackupHistory_c;
      END IF;
      deb(DEB_OPEN, 'dfBackupHistory_c');
      OPEN dfBackupHistory_c(file#      => file#,
                             crescn     => crescn,
                             reset_scn  => reset_scn,
                             reset_time => reset_time);
   END IF;
   IF (getLastBackupHistory.key IS NOT NULL AND
       getLastBackupHistory.ckp_scn = getLastBackupHistory.stop_scn AND
       (backedUpDev IS NULL OR
        getLastBackupHistory.device_type = backedUpDev)) THEN
      -- last file was offline/readonly now and backup on this device
      icount := 1;
   END IF;
   IF (NOT dfBackupHistory_c%ISOPEN) THEN
      eof := TRUE;
      goto lastRow;
   END IF;
<<nextRow>>
   FETCH dfBackupHistory_c INTO local;
   IF (dfBackupHistory_c%NOTFOUND) THEN
      CLOSE dfBackupHistory_c;
      eof := TRUE;
   ELSIF (getLastBackupHistory.key IS NULL OR
          (getLastBackupHistory.dfNumber   = local.dfNumber   AND
           getLastBackupHistory.create_scn = local.create_scn AND
           getLastBackupHistory.reset_scn  = local.reset_scn  AND
           getLastBackupHistory.reset_time = local.reset_time)) THEN
      IF (local.ckp_scn = local.stop_scn AND
          (backedUpDev IS NULL OR local.device_type = backedUpDev)) THEN
         -- this file is offline/readonly now and a bkup on this device
         icount  := icount + 1;          -- bump the number of copies
      END IF;
      getLastBackupHistory := local;     -- remember the last copy
      goto nextRow;
   END IF;
   -- We are here either a different filenumber, create_scn, reset_scn
   -- reset_time is seen or reached the eof
<<lastRow>>
   IF (eof AND getLastBackupHistory.key IS NULL) THEN
      deb(DEB_EXIT, 'with: no_data_found');
      RAISE no_data_found;
   END IF;
   -- the last backup contains the maximum completion time because
   -- we ordered by completion_time
   bhistoryRec             := getLastBackupHistory;
   -- init the number of backups on this device
   bhistoryRec.device_type := backedUpDev;
   bhistoryRec.nbackups    := icount;
   IF (eof) THEN
      getLastBackupHistory.key := NULL; -- for next time to raise no_data
   ELSE
      -- remember the last copy because we haven't returned this yet
      getLastBackupHistory := local;
   END IF;
   deb(DEB_EXIT, 'with file# = ' || to_char(bhistoryRec.dfNumber) ||
                 ' nbackups= '   || to_char(bhistoryRec.nbackups) ||
                 ' compTime= '   || to_char(bhistoryRec.compTime));
END getDfBackupHistory;
PROCEDURE getAlBackupHistory(
   backedUpDev     IN   varchar2
  ,first           IN   boolean
  ,thread#         IN   number  DEFAULT NULL
  ,sequence#       IN   number  DEFAULT NULL
  ,bhistoryRec     OUT  bhistoryRec_t)
IS
   eof       boolean := FALSE;
   local     bhistoryRec_t;
   icount    number  := 0;
BEGIN
   deb(DEB_ENTER, 'getAlBackupHistory');
   IF (first) THEN
      getLastBackupHistory.key := NULL;
      IF (alBackupHistory_c%ISOPEN) THEN
         CLOSE alBackupHistory_c;
      END IF;
      deb(DEB_OPEN, 'alBackupHistory_c');
      OPEN alBackupHistory_c(thread#   => thread#,
                             sequence# => sequence#);
   END IF;
   IF (getLastBackupHistory.key IS NOT NULL AND
       (backedUpDev IS NULL OR
        getLastBackupHistory.device_type = backedUpDev)) THEN
      -- last fetch is a backup on this device
      icount := 1;
   END IF;
   IF (NOT alBackupHistory_c%ISOPEN) THEN
      eof := TRUE;
      goto lastRow;
   END IF;
<<nextRow>>
   FETCH alBackupHistory_c INTO local;
   IF (alBackupHistory_c%NOTFOUND) THEN
      CLOSE alBackupHistory_c;
      eof := TRUE;
   ELSIF (getLastBackupHistory.key IS NULL OR
          (getLastBackupHistory.logThread = local.logThread AND
           getLastBackupHistory.logSequence = local.logSequence)) THEN
      IF (backedUpDev IS NULL OR
          local.device_type = backedUpDev) THEN
         -- a backup exists on this device
         icount  := icount + 1;             -- bump the number of copies
      END IF;
      getLastBackupHistory := local;     -- remember the last copy
      goto nextRow;
   END IF;
   -- We are here either because a different (thread#, sequence#) is seen or
   -- reached the eof
<<lastRow>>
   IF (eof AND getLastBackupHistory.key IS NULL) THEN
      deb(DEB_EXIT, 'with: no_data_found');
      RAISE no_data_found;
   END IF;
   -- the last backup contains the maximum completion time because
   -- we ordered by completion_time
   bhistoryRec := getLastBackupHistory;
   -- init the backup cound and device type
   bhistoryRec.device_type := backedUpDev;
   bhistoryRec.nbackups    := icount;
   IF (eof) THEN
      getLastBackupHistory.key := NULL; -- for next time to raise no_data
   ELSE
      -- remember the last copy because we haven't returned this yet
      getLastBackupHistory := local;
   END IF;
   deb(DEB_EXIT, 'with (thread#, sequence#)=(' ||
                 to_char(bhistoryRec.logThread)  || ',' ||
                 to_char(bhistoryRec.logSequence) || ')' ||
                 ' nbackups= ' || bhistoryRec.nbackups||
                 ' compTime= '   || to_char(bhistoryRec.compTime));
END getAlBackupHistory;
PROCEDURE getBsBackupHistory(
   backedUpDev     IN   varchar2
  ,first           IN   boolean
  ,set_stamp       IN   number  DEFAULT NULL
  ,set_count       IN   number  DEFAULT NULL
  ,bhistoryRec     OUT  bhistoryRec_t)
IS
   eof       boolean := FALSE;
   local     bhistoryRec_t;
   icount    number  := 0;
BEGIN
   deb(DEB_ENTER, 'getBsBackupHistory');
   IF (first) THEN
      getLastBackupHistory.key := NULL;
      IF (bsBackupHistory_c%ISOPEN) THEN
         CLOSE bsBackupHistory_c;
      END IF;
      deb(DEB_OPEN, 'bsBackupHistory_c');
      OPEN bsBackupHistory_c(set_stamp => set_stamp,
                             set_count => set_count);
   END IF;
   IF (getLastBackupHistory.key IS NOT NULL AND
       (backedUpDev IS NULL OR
        getLastBackupHistory.device_type = backedUpDev)) THEN
      -- last backupset fetched is on this device
      icount := 1;
   END IF;
   IF (NOT bsBackupHistory_c%ISOPEN) THEN
      eof := TRUE;
      goto lastRow;
   END IF;
<<nextRow>>
   FETCH bsBackupHistory_c INTO local;
   IF (bsBackupHistory_c%NOTFOUND) THEN
      CLOSE bsBackupHistory_c;
      eof := TRUE;
   ELSIF (getLastBackupHistory.key IS NULL OR
          getLastBackupHistory.key = local.key) THEN
      IF (backedUpDev IS NULL OR
          local.device_type = backedUpDev) THEN
         icount := icount + 1;          -- bump the number of copies
      END IF;
      getLastBackupHistory := local;  -- remember the last copy
      goto nextRow;
   END IF;
   -- We are here either because a different key is seen or
   -- reached the eof
<<lastRow>>
   IF (eof AND getLastBackupHistory.key IS NULL) THEN
      deb(DEB_EXIT, 'with: no_data_found');
      RAISE no_data_found;
   END IF;
   -- the last backup contains the maximum completion time because
   -- we ordered by completion_time
   bhistoryRec := getLastBackupHistory;
   -- init the device type and number of backups
   bhistoryRec.device_type := backedUpDev;
   bhistoryRec.nbackups    := icount;
   IF (eof) THEN
      getLastBackupHistory.key := NULL; -- for next time to raise no_data
   ELSE
      -- remember the last copy because we haven't returned this yet
      getLastBackupHistory := local;
   END IF;
   deb(DEB_EXIT, 'with set_stamp = ' || to_char(bhistoryRec.setStamp) ||
                 'set_count = ' || to_char(bhistoryRec.setCount) ||
                 ' nbackups= '  || to_char(bhistoryRec.nbackups)  ||
                 ' compTime= '  || to_char(bhistoryRec.compTime));
END getBsBackupHistory;
-- Obsolete as of 9.0.1
-- DataFile History
PROCEDURE getBackupHistory(
   dfRec            IN  dfRec_t
  ,backedUpDev      IN  varchar2
  ,nbackupsFlag     IN  number
  ,bscompletionFlag IN  number
  ,nbackups         OUT number
  ,bscompletion     OUT date)
IS
   bhistoryRec  bhistoryRec_t;
BEGIN
   deb(DEB_ENTER, 'getBackupHistory');
   nbackups := 0;
   bscompletion := NULL;
   -- not interested in history
   IF ((nbackupsFlag != 1  OR backedUpDev IS NULL) AND
       bscompletionFlag != 1) THEN
      deb(DEB_EXIT, 'with not interested');
      RETURN;
   END IF;
   getDfBackupHistory(
      backedUpDev     => backedUpDev
     ,first           => TRUE
     ,file#           => dfRec.dfNumber
     ,crescn          => dfRec.dfCreationSCN
     ,bhistoryRec     => bhistoryRec
   );
   IF (dfBackupHistory_c%ISOPEN) THEN
      CLOSE dfBackupHistory_c;
   END IF;
   getLastBackupHistory.key := NULL;
   nbackups     := bhistoryRec.nbackups;
   bscompletion := bhistoryRec.compTime;
  
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT);
      nbackups := 0;
      bscompletion := NULL;
END getBackupHistory;
-- Obsolete as of 9.0.1
-- Archivelog History
PROCEDURE getBackupHistory(
   alRec            IN  alRec_t
  ,backedUpDev      IN  varchar2
  ,nbackupsFlag     IN  number
  ,bscompletionFlag IN  number
  ,nbackups         OUT number
  ,bscompletion     OUT date)
IS
   bhistoryRec   bhistoryRec_t;
BEGIN
   deb(DEB_ENTER, 'getBackupHistory');
   nbackups := 0;
   bscompletion := NULL;
   -- not interested in history
   IF ((nbackupsFlag != 1  OR backedUpDev IS NULL) AND
       bscompletionFlag != 1) THEN
      deb(DEB_EXIT, 'with not interested');
      RETURN;
   END IF;
   getAlBackupHistory(
      backedUpDev     => backedUpDev
     ,first           => TRUE
     ,thread#         => alRec.thread
     ,sequence#       => alRec.sequence
     ,bhistoryRec     => bhistoryRec
   );
   IF (alBackupHistory_c%ISOPEN) THEN
      CLOSE alBackupHistory_c;
   END IF;
   getLastBackupHistory.key := NULL;
   nbackups     := bhistoryRec.nbackups;
   bscompletion := bhistoryRec.compTime;
  
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT);
      nbackups := 0;
      bscompletion := NULL;
END;
-- Obsolete as of 9.0.1
-- BackupPiece History
PROCEDURE getBackupHistory(
   bpRec            IN  bpRec_t
  ,backedUpDev      IN  varchar2
  ,nbackupsFlag     IN  number
  ,bscompletionFlag IN  number
  ,nbackups         OUT number
  ,bscompletion     OUT date)
IS
   bhistoryRec     bhistoryRec_t;
BEGIN
   deb(DEB_ENTER, 'getBackupHistory');
   nbackups := 0;
   bscompletion := NULL;
   -- not interested in history
   IF ((nbackupsFlag != 1  OR backedUpDev IS NULL) AND
       bscompletionFlag != 1) THEN
      deb(DEB_EXIT, 'with not interested');
      RETURN;
   END IF;
   getbsBackupHistory(
      backedUpDev     => backedUpDev
     ,set_stamp       => bpRec.setStamp
     ,set_count       => bpRec.setCount
     ,first           => TRUE
     ,bhistoryRec     => bhistoryRec
   );
   IF (bsBackupHistory_c%ISOPEN) THEN
      CLOSE bsBackupHistory_c;
   END IF;
   getLastBackupHistory.key := NULL;
   nbackups     := bhistoryRec.nbackups;
   bscompletion := bhistoryRec.compTime;
  
   deb(DEB_EXIT);
EXCEPTION
   WHEN no_data_found THEN
      deb(DEB_EXIT);
      nbackups := 0;
      bscompletion := NULL;
END;
------------------
-- Version Info --
------------------
-- Return all the protocol versions that we support, one at a time.
-- Return them in ascending version number order.
------------------------------ getPackageVersion ------------------------------
FUNCTION getPackageVersion
RETURN varchar2 IS
BEGIN
   deb(DEB_ENTER, 'getPackageVersion');
   IF (versionCounter > versionMaxIndex) THEN
      versionCounter := 1;
      deb(DEB_EXIT, 'with: NULL');
      RETURN NULL;
   END IF;
   versionCounter := versionCounter + 1;
   deb(DEB_EXIT, 'with: '||versionList(versionCounter - 1));
   RETURN versionList(versionCounter - 1);
END getPackageVersion;
FUNCTION isStatusMatch(status      IN VARCHAR2,
                       mask        IN NUMBER) RETURN NUMBER IS
BEGIN
   -- BSpartial_avail is a backupset validation mask and NOT a backuppiece
   -- filter.  For eg. BSpartial_avail + BSavailable + BSexpired means
   -- select 'A' and 'X' pieces but validate the pieces in such a way
   -- partial backupset succeeds. (see findValidBackupSet_c cursor)
   IF (bitand(mask, BSavailable)     != 0 AND status = 'A') OR
      (bitand(mask, BSunavailable)   != 0 AND status = 'U') OR
      (bitand(mask, BSdeleted)       != 0 AND status = 'D') OR
      (bitand(mask, BSexpired)       != 0 AND status = 'X') THEN
      RETURN TRUE#;
   ELSE
      RETURN FALSE#;
   END IF;
END isStatusMatch;
----------------------------- isBackupTypeMatch -------------------------------
FUNCTION isBackupTypeMatch(btype       IN VARCHAR2,
                           mask        IN binary_integer) RETURN NUMBER IS
BEGIN
   IF (bitand(mask, BSdatafile_full) !=0  AND  btype = 'D') OR
      (bitand(mask, BSdatafile_incr) !=0  AND  btype = 'I') OR
      (bitand(mask, BSarchivelog)    !=0  AND  btype = 'L') THEN
      RETURN TRUE#;
   ELSE
      RETURN FALSE#;
   END IF;
END isBackupTypeMatch;
---------------------------
-- Package Instantiation --
---------------------------
BEGIN
   -- initialize version list.
   -- change version_max_index when adding new values.
   versionList(1) := '08.00.04';
   versionList(2) := '08.00.05';
   versionList(3) := '08.01.03';
   versionList(4) := '08.01.05';
   versionList(5) := '08.01.06';
   versionList(6) := '08.01.07';
   versionList(7) := '09.00.00';
   versionList(8) := '09.02.00';
   -- initialize version list iterator variables
   versionCounter := 1;
   versionMaxIndex := 8; -- must match highest index used above
   resetAll;            -- init package variables to defaults
END dbms_rcvman;

See Also

List of packages