saa内部解析:PACKAGE BODY prvt_advisor

PACKAGE BODY prvt_advisor
IS
PROCEDURE VALIDATE_DIRECTIVE (L_DIR_ID         BINARY_INTEGER)
  IS
  L_CNT BINARY_INTEGER;
BEGIN
  SELECT COUNT(*) INTO L_CNT
    FROM SYS.WRI$_ADV_DIRECTIVE_DEFS
    WHERE ID = L_DIR_ID;
  IF L_CNT = 0 THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_DIRECTIVE, L_DIR_ID); 
  END IF;
END VALIDATE_DIRECTIVE;
FUNCTION LOOKUP_DIR_INSTANCE (L_DIR_ID    BINARY_INTEGER,
                              L_NAME      VARCHAR2,
                              L_TASK_ID   BINARY_INTEGER)
  RETURN BINARY_INTEGER
  IS
  L_CNT BINARY_INTEGER;
  L_INST_ID BINARY_INTEGER := 0;
BEGIN
  SELECT COUNT(*) INTO L_CNT
    FROM SYS.WRI$_ADV_DIRECTIVE_INSTANCES
    WHERE DIR_ID = L_DIR_ID
    AND NAME = L_NAME
    AND TASK_ID = L_TASK_ID;
  IF L_CNT > 0 THEN
    SELECT INST_ID INTO L_INST_ID
      FROM SYS.WRI$_ADV_DIRECTIVE_INSTANCES
      WHERE DIR_ID = L_DIR_ID
      AND NAME = L_NAME
      AND TASK_ID = L_TASK_ID;
  END IF;
  RETURN (L_INST_ID);
END LOOKUP_DIR_INSTANCE;
PROCEDURE X_WRITE_TO_FILE (BUFFER     IN CLOB,
                           DIR        VARCHAR2,
                           FNAME      VARCHAR2)
  AS
  EXTERNAL
  NAME "keauWriteFile"
  LIBRARY DBMS_KEA_LIB
  LANGUAGE C
  WITH CONTEXT
  PARAMETERS
  (CONTEXT,
   BUFFER OCILOBLOCATOR,
   DIR OCISTRING,
   FNAME OCISTRING
  );
PROCEDURE RAISE_TASK_NAME_ERROR (ARG1   VARCHAR2,
                                 PROP   BINARY_INTEGER)
IS
  BUF VARCHAR2(32767);
BEGIN
  IF PROP = TASK_PROP_WORKLOAD THEN
    BUF := FORMAT_MESSAGE(1, INV_WRK_NAME, ADJUST_STRING(ARG1, 30),
                          NULL, NULL, NULL, NULL);
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ADVISOR_ERROR, BUF);
  ELSE
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INVALID_TASK_NAME, 
                                      ADJUST_STRING(ARG1, 30));
  END IF;
END RAISE_TASK_NAME_ERROR;
FUNCTION EXECUTION_EXISTS(EXECUTION_NAME VARCHAR2, TASK_NUM NUMBER)
RETURN BOOLEAN
IS 
  COUNTER NUMBER; 
BEGIN 
  PARSE_NAME(EXECUTION_NAME, TASK_PROP_TASK); 
  SELECT COUNT(*) INTO COUNTER FROM SYS.WRI$_ADV_EXECUTIONS
  WHERE TASK_ID = TASK_NUM AND NAME = EXECUTION_NAME; 
  IF (COUNTER = 0) THEN 
    RETURN FALSE;
  END IF;   
  RETURN TRUE;
END EXECUTION_EXISTS; 
PROCEDURE VALIDATE_EXECUTION_TYPE(ADVISOR_NUM IN BINARY_INTEGER,
                                  EXEC_TYPE   IN VARCHAR2)
  IS
    ETYPE VARCHAR2(30);
  BEGIN
    SELECT NAME INTO ETYPE
    FROM SYS.WRI$_ADV_DEF_EXEC_TYPES
    WHERE ADVISOR_ID = ADVISOR_NUM AND NAME = UPPER(EXEC_TYPE);
    EXCEPTION 
      WHEN NO_DATA_FOUND THEN    
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXECTYPE_NOT_FOUND);
      WHEN OTHERS THEN
       RAISE;
  END VALIDATE_EXECUTION_TYPE;
PROCEDURE  VALIDATE_EXECUTION_TYPE(ADVISOR_NUM      IN     BINARY_INTEGER,
                                   ADVISOR_PROPERTY IN     BINARY_INTEGER,
                                   TASK_NUM         IN     BINARY_INTEGER,
                                   EXEC_TYPE_NAME   IN OUT VARCHAR2, 
                                   EXEC_TYPE_ID     OUT    BINARY_INTEGER)
  IS
  BEGIN
    IF (EXEC_TYPE_NAME IS NOT NULL) THEN
      SELECT NAME, ID  INTO EXEC_TYPE_NAME, EXEC_TYPE_ID
      FROM SYS.WRI$_ADV_DEF_EXEC_TYPES
      WHERE ADVISOR_ID = ADVISOR_NUM AND NAME = UPPER(EXEC_TYPE_NAME);
    ELSIF (BITAND(ADVISOR_PROPERTY, ADV_PROP_MULTI_EXEC) <> 0) THEN 
      SELECT P.VALUE, E.ID INTO EXEC_TYPE_NAME, EXEC_TYPE_ID
      FROM WRI$_ADV_PARAMETERS P,  SYS.WRI$_ADV_DEF_EXEC_TYPES E
      WHERE P.NAME = 'DEFAULT_EXECUTION_TYPE' AND TASK_ID = TASK_NUM AND
            P.VALUE = E.NAME (+) AND ADVISOR_NUM = ADVISOR_ID (+); 
      IF (EXEC_TYPE_NAME IS NULL OR 
          EXEC_TYPE_NAME = 'UNUSED' OR 
          LENGTH(EXEC_TYPE_NAME) = 0) 
      THEN 
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXECTYPE_NOT_SPECIFIED);
      END IF; 
    END IF; 
  EXCEPTION 
    WHEN NO_DATA_FOUND THEN    
      IF (EXEC_TYPE_NAME IS NOT NULL) THEN 
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXECTYPE_NOT_FOUND);
      ELSE
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXECTYPE_NOT_SPECIFIED);
      END IF;
    WHEN OTHERS THEN
     RAISE;
  END VALIDATE_EXECUTION_TYPE;
FUNCTION GET_LAST_EXECUTION(TASK_ID_NUM    IN BINARY_INTEGER, 
                            EXECUTION_TYPE IN VARCHAR2 := NULL)
RETURN VARCHAR2
  IS
   EXEC_NAME VARCHAR2(30);
  BEGIN
    IF (EXECUTION_TYPE IS NULL) THEN
      SELECT LAST_EXEC_NAME 
      INTO   EXEC_NAME 
      FROM SYS.WRI$_ADV_TASKS
      WHERE ID = TASK_ID_NUM;
    ELSE  
      SELECT MAX(EXECUTION_NAME) KEEP (DENSE_RANK LAST 
                                       ORDER BY EXECUTION_START)
      INTO   EXEC_NAME
      FROM   DBA_ADVISOR_EXECUTIONS E
      WHERE  TASK_ID = TASK_ID_NUM AND
             E.EXECUTION_TYPE = 
               PRVT_ADVISOR.GET_LAST_EXECUTION.EXECUTION_TYPE;
     IF (EXEC_NAME IS NULL) THEN
       SYS.DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(TASK_EXECTYPE_NOT_FOUND);
     END IF;
    END IF;
    RETURN EXEC_NAME; 
  END GET_LAST_EXECUTION;
FUNCTION VALIDATE_EXECUTION(TASK_ID_NUM    IN BINARY_INTEGER,
                            EXECUTION_NAME IN VARCHAR2,
                            EXECUTION_TYPE IN VARCHAR2 := NULL)
RETURN VARCHAR2
  IS
    EXEC_TYPE VARCHAR2(30);
  BEGIN
    IF (EXECUTION_NAME IS NULL OR LENGTH(EXECUTION_NAME) = 0) THEN 
      RETURN GET_LAST_EXECUTION(TASK_ID_NUM, EXECUTION_TYPE); 
    ELSE
      IF (NOT EXECUTION_EXISTS(EXECUTION_NAME, TASK_ID_NUM)) THEN 
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXEC_NOT_FOUND, EXECUTION_NAME);
      END IF;
      IF (EXECUTION_TYPE IS NOT NULL) THEN
        SELECT E.EXECUTION_TYPE 
        INTO   EXEC_TYPE
        FROM   DBA_ADVISOR_EXECUTIONS E
        WHERE  E.TASK_ID = TASK_ID_NUM AND 
               E.EXECUTION_NAME = 
                 PRVT_ADVISOR.VALIDATE_EXECUTION.EXECUTION_NAME;
        IF (EXEC_TYPE <> UPPER(TRIM(EXECUTION_TYPE))) THEN
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_EXECTYPE, EXEC_TYPE, 
                                            UPPER(TRIM(EXECUTION_TYPE)));
        END IF; 
      END IF;
    END IF; 
    RETURN EXECUTION_NAME; 
  END VALIDATE_EXECUTION;
PROCEDURE VALIDATE_OBJECT(TASK_NAME   IN VARCHAR2,
                          TASK_ID_NUM IN BINARY_INTEGER,
                          OBJECT_ID   IN BINARY_INTEGER)
  IS
    OBJ_ID NUMBER := OBJECT_ID;
  BEGIN
    IF (OBJ_ID IS NOT NULL) THEN 
      SELECT ID INTO OBJ_ID 
      FROM SYS.WRI$_ADV_OBJECTS
      WHERE TASK_ID = TASK_ID_NUM AND ID = OBJ_ID;
    END IF; 
  EXCEPTION 
    WHEN NO_DATA_FOUND THEN    
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(OBJECT_NOT_FOUND, OBJECT_ID, TASK_NAME);
    WHEN OTHERS THEN
     RAISE;
  END VALIDATE_OBJECT;
PROCEDURE UPDATE_EXECUTION(
  TASK_NUM   IN BINARY_INTEGER,
  EXEC_NAME  IN VARCHAR2,
  NEW_STATUS IN BINARY_INTEGER := NULL,
  END_DATE   IN DATE           := NULL)
  IS
  BEGIN
    UPDATE SYS.WRI$_ADV_EXECUTIONS
    SET EXEC_MTIME = SYSDATE,
        STATUS = NVL(NEW_STATUS, STATUS),
        EXEC_END = NVL(END_DATE, EXEC_END)
    WHERE TASK_ID = TASK_NUM AND NAME = EXEC_NAME;
  END UPDATE_EXECUTION;
PROCEDURE PROPAGATE_TASK_PARAMETER(
  TASK_NUM    IN BINARY_INTEGER,
  PARAM_NAME  IN VARCHAR,
  ADV_ID      IN NUMBER)
  IS
    OLD_VALUE  SYS.WRI$_ADV_DEF_PARAMETERS.VALUE%TYPE;
    FIRST_TIME BOOLEAN := TRUE;
    CNT NUMBER;
  BEGIN
    FOR REC IN (SELECT E.NAME 
                FROM WRI$_ADV_EXECUTIONS E
                WHERE E.TASK_ID = TASK_NUM AND 
                      NOT EXISTS (SELECT 1 
                                  FROM WRI$_ADV_EXEC_PARAMETERS P
                                  WHERE P.TASK_ID = E.TASK_ID AND 
                                        P.EXEC_NAME = E.NAME AND 
                                        P.NAME = PARAM_NAME))
    LOOP      
      IF (FIRST_TIME) THEN
        SELECT COUNT(*),MAX(VALUE) INTO CNT,OLD_VALUE 
        FROM WRI$_ADV_PARAMETERS 
        WHERE TASK_ID = TASK_NUM AND NAME = PARAM_NAME; 
        IF (CNT = 0) THEN
          SELECT VALUE INTO OLD_VALUE 
          FROM SYS.WRI$_ADV_DEF_PARAMETERS 
          WHERE NAME = PARAM_NAME
            AND (ADVISOR_ID = ADV_ID OR ADVISOR_ID = 0); 
        END IF;
        FIRST_TIME := FALSE;  
      END IF;
      INSERT INTO SYS.WRI$_ADV_EXEC_PARAMETERS(TASK_ID, EXEC_NAME, NAME, VALUE)
      VALUES (TASK_NUM, REC.NAME, PARAM_NAME, OLD_VALUE);
    END LOOP; 
  END PROPAGATE_TASK_PARAMETER;
PROCEDURE POST_PROCESS_TASK(TASK_NUM IN BINARY_INTEGER, 
                            ADV_ID   IN NUMBER,
                            ERR_NUM  IN BINARY_INTEGER,
                            CLEANUP  IN BINARY_INTEGER)
  IS
    L_STATUS   BINARY_INTEGER;
    L_HOW      VARCHAR2(30);    
    TO_COMMIT  BINARY_INTEGER := 0; 
    TO_STATUS  BINARY_INTEGER := 0; 
    NEW_ERRNUM BINARY_INTEGER := NVL(ERR_NUM, 0);
    EXEC_NAME  VARCHAR2(30); 
  BEGIN
    SELECT STATUS#, HOW_CREATED, LAST_EXECUTION 
    INTO L_STATUS, L_HOW, EXEC_NAME
    FROM SYS.DBA_ADVISOR_TASKS
    WHERE TASK_ID = TASK_NUM
    FOR UPDATE;
    IF(NEW_ERRNUM > 0) THEN
      NEW_ERRNUM := (-1 * NEW_ERRNUM);
    END IF;
    TO_STATUS := NULL;
    TO_COMMIT := 0;
    CASE NEW_ERRNUM
      WHEN 0 THEN
         TO_COMMIT := 1;
         IF L_STATUS = TASK_STATE_EXEC THEN
           TO_STATUS := TASK_STATE_COMPLETED;
         END IF; 
      WHEN USER_INTERRUPT THEN 
         TO_COMMIT := 1;
         TO_STATUS := TASK_STATE_INTERRUPTED;
      WHEN TO_INTERRUPT THEN
         TO_COMMIT := 1;
         TO_STATUS := TASK_STATE_INTERRUPTED;
      WHEN WAIT_INTERRUPT THEN
         TO_COMMIT := 1;
         TO_STATUS := TASK_STATE_INTERRUPTED;
      WHEN USER_CANCEL THEN
         TO_STATUS := TASK_STATE_CANCELLED;
      WHEN TO_CANCEL THEN
         TO_STATUS := TASK_STATE_CANCELLED;
      ELSE
         TO_STATUS := TASK_STATE_ERROR;
    END CASE;  
    IF (TO_COMMIT = 1) THEN
      COMMIT;
    ELSE
      ROLLBACK;
    END IF;
    IF (TO_COMMIT = 1  OR TO_STATUS IS NOT NULL) THEN
      UPDATE_EXECUTION(TASK_NUM, EXEC_NAME, TO_STATUS, SYSDATE);
      UPDATE_TASK(TASK_ID => TASK_NUM, NEW_CLEANUP => CLEANUP); 
      IF L_HOW != 'AUTO' THEN
        UPDATE SYS.WRI$_ADV_USAGE
          SET LAST_EXEC_TIME = SYSDATE,
            NUM_EXECS = NUM_EXECS + 1
          WHERE ADVISOR_ID = ADV_ID;
      END IF;
      IF (NEW_ERRNUM != 0) THEN
        RECORD_ERRORMSG(TASK_NUM, EXEC_NAME, -1*NEW_ERRNUM);
      END IF;
      COMMIT;
    END IF;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        RAISE;
  END POST_PROCESS_TASK;
PROCEDURE COMMON_SUB_EXECUTE(
  ADV_OBJ        IN OUT WRI$_ADV_ABSTRACT_T,
  TASK_NUM       IN BINARY_INTEGER,
  TASK_OPERATION IN BINARY_INTEGER)
IS 
  ERR_NUM BINARY_INTEGER := 0;
BEGIN
  IF (TASK_OPERATION = TASK_EXECUTE) THEN
    ADV_OBJ.SUB_EXECUTE(TASK_NUM, ERR_NUM);       
  ELSIF (TASK_OPERATION = TASK_RESUME) THEN
    ADV_OBJ.SUB_RESUME(TASK_NUM, ERR_NUM); 
  END IF;
  POST_PROCESS_TASK(TASK_NUM, ADV_OBJ.ADVISOR_ID, ERR_NUM, 0);
  EXCEPTION 
    WHEN OTHERS THEN
      POST_PROCESS_TASK(TASK_NUM, ADV_OBJ.ADVISOR_ID, SQLCODE, 1);
      RAISE; 
END COMMON_SUB_EXECUTE; 
FUNCTION CHECK_ADVFMWK_TGTOBJ_LIST(TGT_LIST  IN VARCHAR2)
RETURN CLOB
  IS
  L_DELIM       CHAR(1) := ',';
  L_START       NUMBER  := 1;
  L_NP          NUMBER  := 0;
  L_TOKEN       VARCHAR2(4000) := NULL;
  L_NUM         NUMBER;
  XMLOBJ_LIST   CLOB := NULL;
  CUR_OBJ_TAG   VARCHAR2(32767);
  BEGIN
    IF TGT_LIST = 'UNUSED' OR TGT_LIST IS NULL THEN
       RETURN XMLOBJ_LIST;
    END IF;
    DBMS_LOB.CREATETEMPORARY(XMLOBJ_LIST, TRUE);
    DBMS_LOB.WRITEAPPEND(XMLOBJ_LIST, LENGTH(''), '');
    WHILE (L_START <= LENGTH(TGT_LIST)) LOOP
      L_NP := INSTR(TGT_LIST, L_DELIM, L_START);
      IF(L_NP > 0) THEN
        L_TOKEN := SUBSTR(TGT_LIST, L_START, L_NP-L_START);
        L_START := L_NP+1;
      ELSE
        L_TOKEN := SUBSTR(TGT_LIST, L_START, LENGTH(TGT_LIST) - L_START + 1);
        L_START := LENGTH(TGT_LIST)+1;
      END IF;
      BEGIN
        L_NUM := TO_NUMBER(L_TOKEN);
        IF(L_NUM IS NOT NULL) THEN
          CUR_OBJ_TAG :=  '' || L_NUM || '';
          DBMS_LOB.WRITEAPPEND(XMLOBJ_LIST, LENGTH(CUR_OBJ_TAG), CUR_OBJ_TAG);
        END IF;
        EXCEPTION
          WHEN VALUE_ERROR THEN
            DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_NUM_PARAM, 'TARGET_OBJECTS');
          WHEN OTHERS THEN
            RAISE;
      END;
     END LOOP;
     DBMS_LOB.WRITEAPPEND(XMLOBJ_LIST, LENGTH(''), '');
     RETURN XMLOBJ_LIST;
  END CHECK_ADVFMWK_TGTOBJ_LIST;
PROCEDURE VALIDATE_FMWK_PARAMS (TASK_ID_NUM       IN BINARY_INTEGER,
                                ADV_ID            IN BINARY_INTEGER,
                                L_NAME            IN VARCHAR2,
                                L_DATA            IN OUT VARCHAR2)
  IS
   L_NUM  NUMBER;
   FLAGS  BINARY_INTEGER;
   C_DATA VARCHAR2(4000);
   D      DATE;
   FORMAT VARCHAR2(30) := 'MM-DD-YYYY HH24:MI:SS';
   OBJ_XML_LIST CLOB := NULL;
  BEGIN
     C_DATA := TRIM(UPPER(L_DATA));
     CASE
     WHEN L_NAME IN ('DAYS_TO_EXPIRE', 'TIME_LIMIT', 'INSTANCE', 
                     'START_SNAPSHOT', 'END_SNAPSHOT', 
                     'EXECUTION_DAYS_TO_EXPIRE') 
     THEN
        IF C_DATA = 'UNLIMITED' OR C_DATA = 'UNUSED' THEN
          RETURN;
        END IF;
        BEGIN
          L_NUM := TO_NUMBER(L_DATA);
          EXCEPTION
            WHEN VALUE_ERROR THEN
              DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_NUM_PARAM, L_NAME);
            WHEN OTHERS THEN
              RAISE;
        END;
        IF (L_NUM < 0) OR (L_NAME = 'INSTANCE' AND L_NUM < 1) THEN
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ADV_PARAM_VAL, L_NAME);
        END IF;
     WHEN L_NAME = 'TARGET_OBJECTS' THEN
       OBJ_XML_LIST:= CHECK_ADVFMWK_TGTOBJ_LIST(C_DATA);
     WHEN L_NAME = 'MODE' THEN
        SELECT PROPERTY INTO L_NUM
          FROM SYS.WRI$_ADV_DEFINITIONS
          WHERE ID = ADV_ID;
          IF C_DATA = 'COMPREHENSIVE' THEN
            IF BITAND(FLAGS, ADV_PROP_COMPREHENSIVE) = 0 THEN
                DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ADV_PARAM_VAL, L_NAME);
            END IF;
            L_DATA := C_DATA;
          ELSIF C_DATA = 'LIMITED' THEN
            IF BITAND(FLAGS, ADV_PROP_LIMITED) = 0 THEN
               DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ADV_PARAM_VAL, L_NAME);
            END IF;
            L_DATA := C_DATA;
          ELSE
             DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ADV_PARAM_VAL, L_NAME);
          END IF;
     WHEN L_NAME = 'START_TIME' OR L_NAME = 'END_TIME' THEN
        BEGIN
          IF C_DATA = 'CURRENT' OR C_DATA = 'UNUSED' THEN
            RETURN;
          END IF;
          D := TO_DATE (C_DATA, FORMAT);
        EXCEPTION
          WHEN VALUE_ERROR THEN
              DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_DATE_PARAM,
                                                C_DATA, L_NAME, FORMAT);
          WHEN OTHERS THEN
             RAISE;
        END;
     WHEN L_NAME = 'JOURNALING' THEN
       IF C_DATA IN ('0','1','2','3','4','5','6','7','8','9') THEN
         L_NUM := C_DATA;
         SELECT DECODE(L_NUM,0,'UNUSED',1,'FATAL',2,'ERROR',3,'WARNING',
                       4,'INFORMATION',5,'INFORMATION2',6,'INFORMATION3',
                       7,'INFORMATION4',8,'INFORMATION5',
                       9,'INFORMATION6') INTO L_DATA
          FROM DUAL;
       ELSIF C_DATA IN ('UNUSED','FATAL','ERROR','WARNING',
                        'INFORMATION','INFORMATION2','INFORMATION3',
                        'INFORMATION4',
                        'INFORMATION5','INFORMATION6') THEN
          L_DATA := C_DATA;
       ELSE
         DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ADV_PARAM_VAL, L_NAME);
       END IF;
     WHEN L_NAME = 'DEFAULT_EXECUTION_TYPE' THEN 
       IF (L_DATA IS NOT NULL AND LENGTH(L_DATA)!=0 AND L_DATA!='UNUSED') THEN
         VALIDATE_EXECUTION_TYPE(ADV_ID, L_DATA);
       END IF; 
     ELSE 
       NULL; 
     END CASE; 
    EXCEPTION
      WHEN OTHERS THEN
        RAISE;
  END VALIDATE_FMWK_PARAMS;
PROCEDURE VALIDATE_TASK_PARAMETER(
  ADV              IN OUT WRI$_ADV_ABSTRACT_T,
  ADV_PROP         IN     BINARY_INTEGER,
  TASK_NAME        IN     VARCHAR2,
  TASK_NUM         IN     BINARY_INTEGER,
  TASK_STATUS      IN     BINARY_INTEGER,
  TASK_STORED_PROP IN     NUMBER,
  PARAM_SCOPE      IN     BINARY_INTEGER,
  PARAM_NAME       IN OUT VARCHAR2,
  PARAM_DATA       IN OUT VARCHAR2,
  PARAM_FLAGS      OUT    BINARY_INTEGER)
IS
    CNT NUMBER;
    L_FLAGS BINARY_INTEGER;
    L_DEFAULTED BOOLEAN := FALSE;
BEGIN 
    IF PARAM_NAME IS NOT NULL AND LENGTH(PARAM_NAME) > 30 THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'PARAMETER');    
    ELSE
      PARAM_NAME := NVL(UPPER(PARAM_NAME), 'NULL');
    END IF;
    SELECT COUNT(*),MAX(A.FLAGS) INTO CNT,L_FLAGS
      FROM SYS.WRI$_ADV_PARAMETERS A
      WHERE A.TASK_ID = TASK_NUM
        AND A.NAME = PARAM_NAME;
    IF CNT = 0 THEN
      SELECT COUNT(*),MAX(A.FLAGS) INTO CNT,L_FLAGS
        FROM SYS.WRI$_ADV_DEF_PARAMETERS A
        WHERE A.NAME = PARAM_NAME
          AND (A.ADVISOR_ID = ADV.ADVISOR_ID
            OR A.ADVISOR_ID = 0);
      IF CNT = 0 THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(PARAM_NOT_FOUND,
                                          PARAM_NAME,
                                          TASK_NAME);
      END IF;
    END IF;
    IF (TASK_STATUS != TASK_STATE_INITIAL) THEN
      IF ((PARAM_SCOPE = LAST_EXECUTION AND BITAND(L_FLAGS, 8) = 0) OR
          (PARAM_SCOPE = FUTURE_EXECUTIONS AND 
           BITAND(ADV_PROP, ADV_PROP_MULTI_EXEC) = 0 AND 
           BITAND(L_FLAGS, 8) = 0)) 
      THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(SET_PARAM_DISALLOWED, PARAM_NAME);
      END IF;
      IF (TASK_STATUS = TASK_STATE_EXEC) THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(SET_PARAM_DURINGEXEC, PARAM_NAME);
       END IF;
    ELSIF (PARAM_SCOPE = LAST_EXECUTION) THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOEXEC_RESULTS, TASK_NAME);
    END IF;
    IF (BITAND(L_FLAGS, 16) <> 0 AND                             
        BITAND(TASK_STORED_PROP, TASK_PROP_SYSTEMTASK) = 0) THEN 
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(PARAM_NOT_FOUND, 
                                        PARAM_NAME, TASK_NAME);
    END IF;
    IF PARAM_DATA = TO_CHAR(DBMS_ADVISOR.ADVISOR_DEFAULT) THEN
      SELECT A.VALUE INTO PARAM_DATA FROM SYS.WRI$_ADV_DEF_PARAMETERS A
       WHERE (A.ADVISOR_ID = ADV.ADVISOR_ID OR A.ADVISOR_ID = 0)
         AND A.NAME = PARAM_NAME;
      L_DEFAULTED := TRUE;
    ELSIF (LENGTH(PARAM_DATA) > 4000) THEN 
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'VALUE');    
    END IF;
    IF PARAM_DATA IS NULL OR LENGTH(PARAM_DATA) = 0 THEN
      PARAM_DATA := 'UNUSED';
    ELSIF PARAM_DATA=TO_CHAR(DBMS_ADVISOR.ADVISOR_ALL) OR PARAM_DATA='%' THEN
      PARAM_DATA := 'ALL';
    ELSIF PARAM_DATA = TO_CHAR(DBMS_ADVISOR.ADVISOR_CURRENT) THEN
      PARAM_DATA := 'CURRENT';
    ELSIF PARAM_DATA = TO_CHAR(DBMS_ADVISOR.ADVISOR_UNLIMITED) THEN
      PARAM_DATA := 'UNLIMITED';
    ELSIF PARAM_DATA = TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) THEN
      PARAM_DATA := 'UNUSED';
    END IF;
    IF (TRIM(UPPER(PARAM_DATA)) IN ('UNUSED', 'ALL', 'CURRENT', 'UNLIMITED')) 
    THEN
      PARAM_DATA := TRIM(UPPER(PARAM_DATA));
    END IF;
    VALIDATE_FMWK_PARAMS(TASK_NUM, ADV.ADVISOR_ID, PARAM_NAME, PARAM_DATA);
    ADV.SUB_PARAM_VALIDATE(TASK_NUM, PARAM_NAME, PARAM_DATA);
    PARAM_FLAGS := 0;
    IF BITAND(L_FLAGS, 4) = 4 THEN
      PARAM_FLAGS := PARAM_FLAGS + 4;
    ELSIF BITAND(L_FLAGS, 1) = 1 THEN
      PARAM_FLAGS := PARAM_FLAGS + 1;
    END IF;
    PARAM_FLAGS := PARAM_FLAGS + BITAND(L_FLAGS, 8);
    PARAM_FLAGS := PARAM_FLAGS + BITAND(L_FLAGS, 16);
    IF NOT L_DEFAULTED THEN
      PARAM_FLAGS := PARAM_FLAGS + 2;
    END IF;
END VALIDATE_TASK_PARAMETER; 
PROCEDURE SET_EXECUTION_PARAMS(
  ADVISOR          IN OUT WRI$_ADV_ABSTRACT_T,  
  ADVISOR_PROP     IN     BINARY_INTEGER,
  TASK_NAME        IN     VARCHAR2, 
  TASK_NUM         IN     BINARY_INTEGER, 
  TASK_STATUS      IN     BINARY_INTEGER,
  EXECUTION_NAME   IN     VARCHAR2,
  EXECUTION_PARAMS IN     DBMS_ADVISOR.ARGLIST)
IS 
  PARAM_NAME  SYS.WRI$_ADV_DEF_PARAMETERS.VALUE%TYPE;
  PARAM_VALUE SYS.WRI$_ADV_DEF_PARAMETERS.VALUE%TYPE;
  IDX         NUMBER; 
  TASK_STORED_PROP NUMBER;
  FLAGS            BINARY_INTEGER;       
BEGIN 
  IF (EXECUTION_PARAMS IS NOT NULL AND EXECUTION_PARAMS.COUNT != 0) THEN 
    IF (BITAND(ADVISOR_PROP, ADV_PROP_MULTI_EXEC) = 0) THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(SUPPORT_PARAM_LIST);
    END IF; 
    IF (MOD(EXECUTION_PARAMS.COUNT, 2) != 0) THEN 
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_PARAM_LIST);
    END IF; 
    SELECT PROPERTY INTO TASK_STORED_PROP
    FROM WRI$_ADV_TASKS
    WHERE ID = TASK_NUM;
    IDX := 1; 
    LOOP
      PARAM_NAME  := EXECUTION_PARAMS(IDX);
      PARAM_VALUE := EXECUTION_PARAMS(IDX + 1);
      VALIDATE_TASK_PARAMETER(ADVISOR, ADVISOR_PROP, 
                              TASK_NAME, TASK_NUM, TASK_STATUS, 
                              TASK_STORED_PROP,
                              FUTURE_EXECUTIONS, PARAM_NAME, PARAM_VALUE, 
                              FLAGS);   
      INSERT INTO SYS.WRI$_ADV_EXEC_PARAMETERS 
        (TASK_ID, EXEC_NAME, NAME, VALUE)
      VALUES
        (TASK_NUM, EXECUTION_NAME, PARAM_NAME, PARAM_VALUE); 
      IDX :=  IDX + 2;
      EXIT WHEN (IDX >= EXECUTION_PARAMS.COUNT);
    END LOOP; 
  END IF; 
  EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_PARAM_LIST);
    WHEN OTHERS THEN
      RAISE;
END SET_EXECUTION_PARAMS; 
PROCEDURE CREATE_FILE (BUFFER         IN CLOB,
                       LOCATION       IN VARCHAR2,
                       FILENAME       IN VARCHAR2)
  IS
    L_DIR      VARCHAR2(32767);
    L_FILENAME VARCHAR2(32767); 
    L_EP       NUMBER := 0;
    L_FILE     UTL_FILE.FILE_TYPE;
  BEGIN
    L_EP := INSTR(FILENAME, '.', 1);
    IF(L_EP = 0) THEN
      L_FILENAME := FILENAME || '.sql';
    ELSIF SUBSTR(FILENAME, L_EP+1) IS NULL THEN
      L_FILENAME := FILENAME || 'sql';  
    ELSE 
      L_FILENAME := FILENAME;
    END IF;
    L_FILE := UTL_FILE.FOPEN(LOCATION, L_FILENAME,'w', 1000);
    UTL_FILE.FCLOSE(L_FILE);
    SELECT DIRECTORY_PATH INTO L_DIR FROM SYS.DBA_DIRECTORIES
      WHERE DIRECTORY_NAME = LOCATION;
    X_WRITE_TO_FILE (BUFFER, L_DIR, L_FILENAME);
  END CREATE_FILE;
FUNCTION COMMON_CREATE_TASK(TASK_NAME      IN OUT VARCHAR2,
                            DESCRIPTION    VARCHAR2,
                            ADVISOR_TYPE   WRI$_ADV_ABSTRACT_T,
                            PARENT_ID      NUMBER,
                            PARENT_REC_ID  NUMBER,
                            FROM_ID        NUMBER,
                            HOW_CREATED    VARCHAR2,
                            PROP           BINARY_INTEGER)
  RETURN NUMBER
  IS
    TASK_ID_NUM NUMBER;
    ADV_ID NUMBER;
    DESCR VARCHAR2(256);
    BUF    VARCHAR2(30);
    ID   BINARY_INTEGER;
    CNT  BINARY_INTEGER;
    L_HOW VARCHAR2(30);
    TP WRI$_ADV_ABSTRACT_T;
    PARAM SYS.WRI$_ADV_DEF_PARAMETERS%ROWTYPE;
    PARAM2 SYS.WRI$_ADV_PARAMETERS%ROWTYPE;
    CURSOR PARAM_CUR (L_ID NUMBER) IS
        SELECT * FROM SYS.WRI$_ADV_DEF_PARAMETERS A
          WHERE A.ADVISOR_ID IN (L_ID,0);
    CURSOR DIR_CUR (L_ID NUMBER) IS
        SELECT A.ID,B.NAME,B.DATA FROM SYS.WRI$_ADV_DIRECTIVE_DEFS A,
                      SYS.WRI$_ADV_DIRECTIVE_INSTANCES B
          WHERE A.ADVISOR_ID = L_ID
            AND A.ID = B.DIR_ID
            AND B.TASK_ID = 0;
    CURSOR FROM_PARAM_CUR (ID NUMBER) IS
        SELECT * FROM SYS.WRI$_ADV_PARAMETERS A
          WHERE A.TASK_ID = ID;
    CURSOR FROM_DIR_CUR (L_ID NUMBER) IS
        SELECT B.DIR_ID,B.NAME,B.DATA 
          FROM WRI$_ADV_DIRECTIVE_INSTANCES B
          WHERE B.TASK_ID = L_ID;
    L_USER_ID BINARY_INTEGER;
    L_USER VARCHAR2(30);
    L_ADV_NAME VARCHAR2(30);
    L_DIR_ID BINARY_INTEGER;
    L_DIR_NAME VARCHAR2(30);
    L_DIR_DATA CLOB := ' ';
  BEGIN
    TP := ADVISOR_TYPE;
    ADV_ID := ADVISOR_TYPE.ADVISOR_ID;
    SELECT NAME INTO L_ADV_NAME FROM SYS.WRI$_ADV_DEFINITIONS
     WHERE ID = ADV_ID;
    L_USER_ID := SYS_CONTEXT('USERENV', 'SESSION_USERID');
    SELECT NAME INTO L_USER FROM USER$ WHERE USER# = L_USER_ID;
    SELECT SYS.WRI$_ADV_SEQ_TASK.NEXTVAL INTO TASK_ID_NUM
      FROM DUAL;
    TASK_NAME := VALIDATE_NEW_TASK(TASK_NAME, TASK_ID_NUM, PROP);
    IF DESCRIPTION IS NULL THEN
      DESCR := '';
    ELSE
      VALIDATE_ITEM_LENGTH(DESCRIPTION, DESC_NAME, 256);
      DESCR := DESCRIPTION;
    END IF;
    IF HOW_CREATED IS NULL THEN
      L_HOW := 'CMD';
    ELSE
      L_HOW := SUBSTR(HOW_CREATED, 1, 30);
    END IF;
    INSERT INTO SYS.WRI$_ADV_TASKS
      (ID,OWNER#,OWNER_NAME,NAME,DESCRIPTION,ADVISOR_ID,ADVISOR_NAME,
       CTIME,MTIME,PARENT_ID,PARENT_REC_ID, PROPERTY,VERSION,
       EXEC_START,EXEC_END,STATUS,STATUS_MSG_ID,PCT_COMPLETION_TIME,
       PROGRESS_METRIC,METRIC_UNITS,ACTIVITY_COUNTER,REC_COUNT,ERROR_MSG#,
       SOURCE,HOW_CREATED
      )
    VALUES
      (TASK_ID_NUM,L_USER_ID,L_USER,TASK_NAME,DESCR,
       ADV_ID,L_ADV_NAME,SYSDATE,SYSDATE,PARENT_ID,0,PROP, GET_DB_VERSION,
       NULL,NULL, TASK_STATE_INITIAL,0,0,0,'',0,0,0,'',L_HOW
      );
    IF FROM_ID > 0 THEN
      OPEN FROM_PARAM_CUR(FROM_ID);
      LOOP
        FETCH FROM_PARAM_CUR INTO PARAM2;
        EXIT WHEN FROM_PARAM_CUR%NOTFOUND;
        IF BITAND(PARAM2.FLAGS,4) = 4 THEN
          PARAM2.VALUE := '';
        END IF;
        TP.SUB_PARAM_VALIDATE(TASK_ID_NUM, PARAM2.NAME, PARAM2.VALUE);
        INSERT INTO SYS.WRI$_ADV_PARAMETERS
          (TASK_ID,NAME,DATATYPE,VALUE,FLAGS,DESCRIPTION)
        VALUES
          (TASK_ID_NUM, PARAM2.NAME, PARAM2.DATATYPE, PARAM2.VALUE,
           PARAM2.FLAGS, PARAM2.DESCRIPTION);
      END LOOP;
      CLOSE FROM_PARAM_CUR;
      UPDATE SYS.WRI$_ADV_TASKS A
        SET SOURCE = (SELECT B.NAME FROM SYS.WRI$_ADV_TASKS B
                       WHERE B.ID = FROM_ID)
      WHERE ID = TASK_ID_NUM;
      OPEN FROM_DIR_CUR(FROM_ID);
      LOOP
        FETCH FROM_DIR_CUR INTO L_DIR_ID,L_DIR_NAME,L_DIR_DATA;
        EXIT WHEN FROM_DIR_CUR%NOTFOUND;
        INSERT_DIRECTIVE_I (L_DIR_ID,L_DIR_NAME,TASK_ID_NUM,L_DIR_DATA);
      END LOOP;
      CLOSE FROM_DIR_CUR;
    ELSE
      OPEN PARAM_CUR(ADV_ID);
      LOOP
        FETCH PARAM_CUR INTO PARAM;
        EXIT WHEN PARAM_CUR%NOTFOUND;
        TP.SUB_PARAM_VALIDATE(TASK_ID_NUM, PARAM.NAME, PARAM.VALUE);
        INSERT INTO SYS.WRI$_ADV_PARAMETERS
          (TASK_ID,NAME,DATATYPE,VALUE,FLAGS,DESCRIPTION)
        VALUES
          (TASK_ID_NUM, PARAM.NAME, PARAM.DATATYPE, PARAM.VALUE,
           PARAM.FLAGS, PARAM.DESCRIPTION);
      END LOOP;
      CLOSE PARAM_CUR;
      OPEN DIR_CUR(ADV_ID);
      LOOP
        FETCH DIR_CUR INTO L_DIR_ID,L_DIR_NAME,L_DIR_DATA;
        EXIT WHEN DIR_CUR%NOTFOUND;
        INSERT_DIRECTIVE_I(L_DIR_ID,L_DIR_NAME,TASK_ID_NUM,L_DIR_DATA);
      END LOOP;
      CLOSE DIR_CUR;
    END IF;
    TP.SUB_CREATE(TASK_ID_NUM, FROM_ID);
    RETURN TASK_ID_NUM;
    EXCEPTION
      WHEN DUP_VAL_ON_INDEX THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(TASK_ALREADY_EXISTS, TASK_NAME);
      WHEN OTHERS THEN
        RAISE;
  END COMMON_CREATE_TASK;
PROCEDURE COMMON_CLEANUP_TASK (TASK_NUM   IN BINARY_INTEGER)
  IS
    L_CLEANUP BINARY_INTEGER;
    TP SYS.WRI$_ADV_ABSTRACT_T;
  BEGIN
     SELECT CLEANUP INTO L_CLEANUP
       FROM WRI$_ADV_TASKS
       WHERE ID = TASK_NUM;
     IF L_CLEANUP = 0 THEN
        RETURN;
     END IF;
    TP := FETCH_ADVISOR(TASK_NUM);
    UPDATE SYS.WRI$_ADV_TASKS
      SET PCT_COMPLETION_TIME = 0,
          PROGRESS_METRIC = 0,
          METRIC_UNITS = '',
          ACTIVITY_COUNTER = 0,
          REC_COUNT = 0
      WHERE ID = TASK_NUM;
    TP.SUB_CLEANUP(TASK_NUM);
    UPDATE_TASK(TASK_ID => TASK_NUM, NEW_CLEANUP => 0);
    RETURN;
  END COMMON_CLEANUP_TASK;
FUNCTION CHECK_EXPIRATION_COMP(IN_CURRENT_TIME       IN DATE,
                               BASE_TIME             IN DATE,
                               DAYS_TO_EXPIRE_STRING IN VARCHAR2)
RETURN NUMBER
IS
   L_DAYS_TO_EXPIRE NUMBER;
BEGIN
   IF DAYS_TO_EXPIRE_STRING = 'UNLIMITED' THEN
     RETURN 0;
   ELSIF DAYS_TO_EXPIRE_STRING = 'UNUSED' THEN
      L_DAYS_TO_EXPIRE := 30;
   ELSE
      L_DAYS_TO_EXPIRE := TO_NUMBER(DAYS_TO_EXPIRE_STRING);
   END IF;
   IF L_DAYS_TO_EXPIRE <> 0 AND
     (IN_CURRENT_TIME - BASE_TIME) > L_DAYS_TO_EXPIRE THEN
      RETURN 1;
   ELSE
      RETURN 0;
   END IF;
END CHECK_EXPIRATION_COMP;
FUNCTION CHECK_EXPIRATION(L_TASK_ID IN BINARY_INTEGER,
                          EXECUTION_NAME IN VARCHAR2,
                          IN_CURRENT_TIME IN DATE)
RETURN BOOLEAN
IS
   L_BASE_TIME DATE;
   L_DAYS_TO_EXPIRE_STRING VARCHAR2(50);
BEGIN
   IF (EXECUTION_NAME IS NULL) THEN
     SELECT MTIME INTO L_BASE_TIME
     FROM WRI$_ADV_TASKS
     WHERE ID = L_TASK_ID ;
   ELSE
     SELECT EXEC_MTIME INTO L_BASE_TIME
     FROM WRI$_ADV_EXECUTIONS
     WHERE TASK_ID = L_TASK_ID AND
           NAME = EXECUTION_NAME;
   END IF;
   IF (EXECUTION_NAME IS NULL) THEN
   SELECT VALUE INTO L_DAYS_TO_EXPIRE_STRING
     FROM WRI$_ADV_PARAMETERS
     WHERE TASK_ID = L_TASK_ID AND NAME = 'DAYS_TO_EXPIRE';
   ELSE
     SELECT VALUE INTO L_DAYS_TO_EXPIRE_STRING
       FROM WRI$_ADV_PARAMETERS
       WHERE TASK_ID = L_TASK_ID AND NAME = 'EXECUTION_DAYS_TO_EXPIRE';
   END IF;
   RETURN CHECK_EXPIRATION_COMP(IN_CURRENT_TIME, L_BASE_TIME, 
                                L_DAYS_TO_EXPIRE_STRING) <> 0;
END CHECK_EXPIRATION;
PROCEDURE GATHER_STATISTICS(
  OBJECT_NAME_FILT1 IN VARCHAR2 := 'WRI$_ADV_%',
  OBJECT_NAME_FILT2 IN VARCHAR2 := NULL,
  OBJECT_NAME_FILT3 IN VARCHAR2 := NULL,
  STALE_ONLY        IN BOOLEAN  := TRUE)
IS
  CUR_STALE_ONLY NUMBER;
  CURSOR STAT_OBJ_CUR (OBJ_NAME_PRFX1 IN VARCHAR2, OBJ_NAME_PRFX2 IN VARCHAR2, 
                       OBJ_NAME_PRFX3 IN VARCHAR2, STALE_ONLY IN NUMBER) IS
   (SELECT TABLE_NAME OBJECT_NAME, 'TABLE' OBJECT_TYPE
    FROM DBA_TAB_STATISTICS
    WHERE OWNER        = 'SYS' AND
          (TABLE_NAME  LIKE OBJ_NAME_PRFX1 OR
           TABLE_NAME  LIKE OBJ_NAME_PRFX2 OR
           TABLE_NAME  LIKE OBJ_NAME_PRFX3) AND
          (STALE_ONLY  = 0 OR
           STALE_STATS IS NULL OR
           STALE_STATS = 'YES'))
   UNION ALL
   (SELECT INDEX_NAME OBJECT_NAME, 'INDEX' OBJECT_TYPE
   FROM DBA_IND_STATISTICS
   WHERE OWNER        = 'SYS' AND
         (INDEX_NAME  LIKE OBJ_NAME_PRFX1 OR
          INDEX_NAME  LIKE OBJ_NAME_PRFX2 OR
          INDEX_NAME  LIKE OBJ_NAME_PRFX3 OR
          TABLE_NAME  LIKE OBJ_NAME_PRFX1 OR
          TABLE_NAME  LIKE OBJ_NAME_PRFX2 OR
          TABLE_NAME  LIKE OBJ_NAME_PRFX3) AND
         (STALE_ONLY  = 0 OR
         STALE_STATS  IS NULL OR
         STALE_STATS  = 'YES'));
BEGIN
    IF (STALE_ONLY) THEN
      CUR_STALE_ONLY := 1;
      DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
    ELSE
      CUR_STALE_ONLY := 0;
    END IF;
    FOR RREC IN STAT_OBJ_CUR(OBJECT_NAME_FILT1, OBJECT_NAME_FILT2, 
                             OBJECT_NAME_FILT3, CUR_STALE_ONLY) LOOP
      BEGIN
        CASE RREC.OBJECT_TYPE
          WHEN 'TABLE' THEN
            DBMS_STATS.GATHER_TABLE_STATS('SYS', RREC.OBJECT_NAME);    
          WHEN 'INDEX' THEN
            DBMS_STATS.GATHER_INDEX_STATS('SYS', RREC.OBJECT_NAME);
          ELSE
            RAISE_APPLICATION_ERROR(-20000, 
                                    'invalid objtype from gather stats query',
                                    TRUE);
        END CASE;
        EXCEPTION
          WHEN OTHERS THEN
            IF (SQLCODE = -54 OR SQLCODE = -4022) THEN
              NULL;
            ELSE
              RAISE;
            END IF;
      END;   
    END LOOP;     
END GATHER_STATISTICS;
PROCEDURE GET_GATHER_STATS_INFO(NUM_OBJECTS   OUT  NUMBER,
                                CURRENT_TIME  OUT  DATE, 
                                TASK_ID       IN  BINARY_INTEGER)
  IS
  BEGIN
    SELECT COUNT(*) INTO NUM_OBJECTS
    FROM WRI$_ADV_OBJECTS O
    WHERE O.TASK_ID = GET_GATHER_STATS_INFO.TASK_ID; 
    CURRENT_TIME := SYSDATE;
  END GET_GATHER_STATS_INFO;
FUNCTION DECIDE_GATHER_STATS(PRIOR_NUM_OBJECTS        IN  NUMBER,
                             START_TIME               IN  DATE, 
                             TASK_ID                  IN  BINARY_INTEGER,
                             OPERATION_TYPE           IN  BINARY_INTEGER)
RETURN BOOLEAN
  IS
    POST_NUM_OBJECTS   NUMBER := 0;
    END_TIME           DATE;
  BEGIN
    GET_GATHER_STATS_INFO(POST_NUM_OBJECTS, END_TIME, TASK_ID);
    IF(OPERATION_TYPE = STATS_OPER_DELETE) THEN
      IF ((PRIOR_NUM_OBJECTS - POST_NUM_OBJECTS) > STATS_THRESHOLD_OBJECTS) THEN
        RETURN TRUE;
      END IF;
    ELSIF(OPERATION_TYPE = STATS_OPER_EXECUTE) THEN
      IF ((POST_NUM_OBJECTS - PRIOR_NUM_OBJECTS) > STATS_THRESHOLD_OBJECTS OR 
         (END_TIME - START_TIME)*24*60 > STATS_THRESHOLD_MINS) THEN 
        RETURN TRUE;
      END IF;
    END IF;
    RETURN FALSE;
  END DECIDE_GATHER_STATS;
PROCEDURE COMMON_DELETE_TASK(TASK_ID_NUM    IN BINARY_INTEGER,
                             EXECUTION_NAME IN VARCHAR2 := NULL,
                             DELETE_OPTIONS IN BINARY_INTEGER := DEL_OPT_NONE)
  IS
    TP SYS.WRI$_ADV_ABSTRACT_T;
    LOCK_TIMEOUT BINARY_INTEGER DEFAULT 2;
    LAST_ENAME   SYS.WRI$_ADV_EXECUTIONS.NAME%TYPE;
    PRIOR_NUM_OBJECTS NUMBER;
    START_TIME DATE;
    FLAGS BINARY_INTEGER;   
    GATHER_STATS BOOLEAN;
  BEGIN
    GATHER_STATS := FALSE;
    IF BITAND(DELETE_OPTIONS, DEL_OPT_EXPIRED) != 0 THEN
      LOCK_TIMEOUT := 0;
    END IF;
    TP := FETCH_ADVISOR(TASK_ID_NUM);
    SELECT PROPERTY INTO FLAGS FROM SYS.WRI$_ADV_DEFINITIONS
    WHERE ID = TP.ADVISOR_ID;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_X, LOCK_TIMEOUT);
    IF(BITAND(DELETE_OPTIONS, DEL_OPT_NO_STATS) = 0 AND 
       BITAND(FLAGS, ADV_PROP_GATHER_STATS) <> 0) THEN
      GET_GATHER_STATS_INFO(PRIOR_NUM_OBJECTS, START_TIME, TASK_ID_NUM);
    END IF;
    IF BITAND(DELETE_OPTIONS, DEL_OPT_EXPIRED) != 0 THEN
       IF NOT CHECK_EXPIRATION(TASK_ID_NUM, EXECUTION_NAME, SYSDATE) THEN
          HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
          RETURN;
      END IF;
    END IF;
    IF (EXECUTION_NAME IS NULL) THEN
      TP.SUB_DELETE(TASK_ID_NUM);
    ELSE
      TP.SUB_DELETE_EXECUTION(TASK_ID_NUM, EXECUTION_NAME);
    END IF;
    DELETE FROM SYS.WRI$_ADV_INST_FDG A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    DELETE FROM WRI$_ADV_MESSAGE_GROUPS A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    DELETE FROM WRI$_ADV_OBJECTS A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    DELETE FROM WRI$_ADV_REC_ACTIONS A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR 
           EXISTS (SELECT 1
                   FROM   WRI$_ADV_RECOMMENDATIONS B
                   WHERE  B.TASK_ID = TASK_ID_NUM AND
                          B.ID = A.REC_ID AND
                          B.EXEC_NAME = EXECUTION_NAME));
    DELETE FROM WRI$_ADV_RATIONALE A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    DELETE FROM WRI$_ADV_ACTIONS A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    IF (EXECUTION_NAME IS NULL) THEN
      DELETE FROM WRI$_ADV_DIRECTIVE_INSTANCES A WHERE A.TASK_ID = TASK_ID_NUM;
    END IF;
    DELETE FROM WRI$_ADV_JOURNAL A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    IF (EXECUTION_NAME IS NULL) THEN
      DELETE FROM WRI$_ADV_PARAMETERS A WHERE A.TASK_ID = TASK_ID_NUM;
    END IF;
    DELETE FROM WRI$_ADV_RECOMMENDATIONS A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    DELETE FROM WRI$_ADV_FINDINGS A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    DELETE FROM WRI$_ADV_EXECUTIONS A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.NAME);
    DELETE FROM WRI$_ADV_EXEC_PARAMETERS A 
    WHERE A.TASK_ID = TASK_ID_NUM AND
          (EXECUTION_NAME IS NULL OR EXECUTION_NAME = A.EXEC_NAME);
    DELETE FROM WRI$_ADV_SQLT_PLAN_STATS S
    WHERE EXISTS (SELECT 1 
                  FROM   WRI$_ADV_SQLT_PLAN_HASH PH 
                  WHERE  PH.PLAN_ID = S.PLAN_ID AND
                         PH.TASK_ID = TASK_ID_NUM AND
                         (EXECUTION_NAME IS NULL OR 
                          PH.EXEC_NAME = EXECUTION_NAME));
    DELETE FROM WRI$_ADV_SQLT_PLANS P
    WHERE EXISTS (SELECT 1 
                  FROM   WRI$_ADV_SQLT_PLAN_HASH PH 
                  WHERE  PH.PLAN_ID = P.PLAN_ID AND
                         PH.TASK_ID = TASK_ID_NUM AND
                         (EXECUTION_NAME IS NULL OR 
                          PH.EXEC_NAME = EXECUTION_NAME));
    DELETE FROM  WRI$_ADV_SQLT_PLAN_HASH
    WHERE TASK_ID = TASK_ID_NUM AND 
          (EXECUTION_NAME IS NULL OR EXEC_NAME = EXECUTION_NAME);
    IF (EXECUTION_NAME IS NULL) THEN
    DELETE FROM WRI$_ADV_TASKS A WHERE A.ID = TASK_ID_NUM;
    END IF;
    IF (EXECUTION_NAME IS NOT NULL) THEN
      SELECT MAX(E.NAME) KEEP (DENSE_RANK LAST ORDER BY EXEC_START)
      INTO   LAST_ENAME
      FROM   WRI$_ADV_EXECUTIONS E
      WHERE  E.TASK_ID = TASK_ID_NUM;
      UPDATE_TASK(TASK_ID => TASK_ID_NUM, 
                  LAST_EXECUTION => LAST_ENAME);
    END IF;
    IF(BITAND(DELETE_OPTIONS, DEL_OPT_NO_STATS) = 0 AND
       BITAND(FLAGS, ADV_PROP_GATHER_STATS) <> 0) THEN
         GATHER_STATS := DECIDE_GATHER_STATS(PRIOR_NUM_OBJECTS  => 
                                                        PRIOR_NUM_OBJECTS,
                                             START_TIME         => START_TIME,
                                             TASK_ID            => TASK_ID_NUM,
                                             OPERATION_TYPE     => 
                                                        STATS_OPER_DELETE);
    END IF;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
    IF(GATHER_STATS) THEN
      GATHER_STATISTICS();
    END IF;
  EXCEPTION
      WHEN OTHERS THEN
        HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
        RAISE;
  END COMMON_DELETE_TASK;
PROCEDURE COMMON_RESET_TASK(TASK_NUM   IN BINARY_INTEGER)
  IS
    TP                 SYS.WRI$_ADV_ABSTRACT_T;
    TARGET_OBJECT_LIST VARCHAR2(4000) := NULL;        
    TASK_NAME          VARCHAR2(30);                  
    OBJ_XML_LIST       CLOB := NULL;
  BEGIN
    TP := FETCH_ADVISOR(TASK_NUM);
    TP.SUB_RESET(TASK_NUM); 
    UPDATE SYS.WRI$_ADV_TASKS
      SET EXEC_START = NULL,
          EXEC_END = NULL,
          STATUS = TASK_STATE_INITIAL,
          LAST_EXEC_NAME = NULL,
          STATUS_MSG_ID = 0,
          PCT_COMPLETION_TIME = 0,
          PROGRESS_METRIC = 0,
          METRIC_UNITS = '',
          ACTIVITY_COUNTER = 0,
          REC_COUNT = 0,
          ERROR_MSG# = 0
      WHERE ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_REC_ACTIONS A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_RATIONALE A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_ACTIONS A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_FINDINGS A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_INST_FDG A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_JOURNAL A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_RECOMMENDATIONS A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_MESSAGE_GROUPS A
     WHERE A.TASK_ID = TASK_NUM
       AND A.ID > 0;
    DELETE FROM SYS.WRI$_ADV_EXECUTIONS A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM SYS.WRI$_ADV_EXEC_PARAMETERS A WHERE A.TASK_ID = TASK_NUM;
    DELETE FROM  WRI$_ADV_SQLT_PLANS
    WHERE PLAN_ID IN (SELECT PLAN_ID 
                      FROM WRI$_ADV_SQLT_PLAN_HASH
                      WHERE TASK_ID = TASK_NUM);
    DELETE FROM WRI$_ADV_SQLT_PLAN_STATS
    WHERE PLAN_ID IN (SELECT PLAN_ID 
                      FROM WRI$_ADV_SQLT_PLAN_HASH
                      WHERE TASK_ID = TASK_NUM);
    DELETE FROM WRI$_ADV_SQLT_PLAN_HASH
    WHERE TASK_ID = TASK_NUM;
    SELECT T.NAME,  P.VALUE INTO TASK_NAME, TARGET_OBJECT_LIST
    FROM WRI$_ADV_PARAMETERS P, WRI$_ADV_TASKS T
    WHERE P.TASK_ID = T.ID AND
          P.TASK_ID = TASK_NUM AND P.NAME = 'TARGET_OBJECTS';
    OBJ_XML_LIST := CHECK_ADVFMWK_TGTOBJ_LIST(TARGET_OBJECT_LIST);
    IF (TARGET_OBJECT_LIST IS NOT NULL AND TARGET_OBJECT_LIST != 'UNUSED') THEN
      DELETE FROM WRI$_ADV_OBJECTS
        WHERE TASK_ID = TASK_NUM AND
              ID NOT IN (SELECT EXTRACTVALUE(VALUE(P), 'obj') OBJ_ID
                      FROM TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(OBJ_XML_LIST),
                                             'objects/obj'))) P);
    END IF;
    UPDATE_TASK(TASK_NUM);
    RETURN;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(PARAM_NOT_FOUND,
                                    'TARGET_OBJECTS',
                                    TASK_NAME);
      WHEN OTHERS THEN RAISE;
  END COMMON_RESET_TASK;
PROCEDURE INSERT_ADV_DEFINITION(L_ID    NUMBER,
                                L_NAME  VARCHAR2,
                                L_PROP  NUMBER,
                                L_TYPE  WRI$_ADV_ABSTRACT_T)
  IS
    L_CNT BINARY_INTEGER;
  BEGIN
    SELECT COUNT(*) INTO L_CNT FROM WRI$_ADV_DEFINITIONS
      WHERE ID = L_ID;
    IF L_CNT = 0 THEN
      INSERT INTO WRI$_ADV_DEFINITIONS
        (ID, NAME, PROPERTY, TYPE)
      VALUES (L_ID, L_NAME, L_PROP, L_TYPE);
    ELSE 
      UPDATE WRI$_ADV_DEFINITIONS
      SET PROPERTY = L_PROP,
          TYPE = L_TYPE
      WHERE ID = L_ID;
    END IF;
    SELECT COUNT(*) INTO L_CNT FROM WRI$_ADV_USAGE
      WHERE ADVISOR_ID = L_ID;
    IF L_CNT = 0 THEN
      INSERT INTO WRI$_ADV_USAGE
        (ADVISOR_ID, LAST_EXEC_TIME, NUM_EXECS, NUM_DB_REPORTS)
      VALUES
        (L_ID, SYSDATE, 0, 0);
    END IF;
  END INSERT_ADV_DEFINITION;
PROCEDURE INSERT_DEF_PARAMETER (L_ID        NUMBER,
                                L_NAME      VARCHAR2,
                                L_DTYPE     NUMBER,
                                L_VALUE     VARCHAR2,
                                L_FLAGS     NUMBER,
                                L_DESC      VARCHAR2 := NULL,
                                L_EXEC_TYPE VARCHAR2 := NULL)
  IS
    L_CNT BINARY_INTEGER;
  BEGIN
    SELECT COUNT(*) INTO L_CNT FROM WRI$_ADV_DEF_PARAMETERS
      WHERE ADVISOR_ID = L_ID AND NAME = L_NAME;
    IF L_CNT = 0 THEN
      INSERT INTO WRI$_ADV_DEF_PARAMETERS
        (ADVISOR_ID, NAME, DATATYPE, VALUE, FLAGS, DESCRIPTION, EXEC_TYPE)
      VALUES
        (L_ID, L_NAME, L_DTYPE, L_VALUE, L_FLAGS, L_DESC, L_EXEC_TYPE);
    ELSE
      UPDATE WRI$_ADV_DEF_PARAMETERS
        SET DESCRIPTION = L_DESC,
            FLAGS = L_FLAGS,
            VALUE = L_VALUE,
            EXEC_TYPE = L_EXEC_TYPE
      WHERE ADVISOR_ID = L_ID
        AND NAME = L_NAME;
    END IF;
  END INSERT_DEF_PARAMETER;
PROCEDURE INSERT_DEF_EXECUTION_TYPE(
  L_ADV_ID NUMBER, 
  L_ID     NUMBER,
  L_NAME   VARCHAR2,
  L_FLAGS  NUMBER := NULL,
  L_DESC   VARCHAR2 := NULL)
  IS
  BEGIN
    MERGE INTO WRI$_ADV_DEF_EXEC_TYPES T1 
    USING (SELECT L_ADV_ID ADV, L_ID ID, L_NAME NAME, 
                  L_FLAGS FLAGS, L_DESC DESCP 
           FROM DUAL) T2 
    ON (T1.ADVISOR_ID = T2.ADV AND T1.NAME = T2.NAME) 
    WHEN MATCHED THEN 
      UPDATE SET T1.DESCRIPTION = T2.DESCP, T1.FLAGS = T2.FLAGS 
    WHEN NOT MATCHED THEN 
      INSERT(ADVISOR_ID, NAME, ID, DESCRIPTION, FLAGS) 
      VALUES (T2.ADV, T2.NAME, T2.ID, T2.DESCP, T2.FLAGS);
  END INSERT_DEF_EXECUTION_TYPE;
PROCEDURE CANCEL_TASK (TASK_NAME       IN VARCHAR2)
  IS
    L_ID BINARY_INTEGER := 0;
    STATUS_VALUE BINARY_INTEGER;
    EXEC_NAME VARCHAR2(30); 
  BEGIN
    L_ID := VALIDATE_TASK(TASK_NAME);
    SELECT A.STATUS#, A.LAST_EXECUTION INTO STATUS_VALUE, EXEC_NAME
    FROM SYS.DBA_ADVISOR_TASKS A
    WHERE A.TASK_ID = L_ID
    FOR UPDATE;
    IF STATUS_VALUE != TASK_STATE_EXEC THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOT_EXECUTING, TASK_NAME);
    END IF;
    UPDATE WRI$_ADV_EXECUTIONS A
      SET A.STATUS = TASK_STATE_CANCELLED
    WHERE TASK_ID = L_ID AND NAME = EXEC_NAME;
    SIGNAL_INTERRUPT(L_ID, TASK_INTR_C);
    COMMIT;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
      RAISE;
    RETURN;
  END CANCEL_TASK;
PROCEDURE DELETE_TASK(TASK_NAME       IN VARCHAR2,
                      PROP            IN BINARY_INTEGER := TASK_PROP_TASK)
  IS
    TASK_ID NUMBER := 0;
    L_USER_ID BINARY_INTEGER;
    L_PROP BINARY_INTEGER;
    A_PROP BINARY_INTEGER;
    BIT_EXCLUSIONS BINARY_INTEGER;
    CURSOR TASK_CUR (IN_NAME VARCHAR2,IN_PROP BINARY_INTEGER,
                     IN_OWNER BINARY_INTEGER) IS
        SELECT ID, PROPERTY
          FROM SYS.WRI$_ADV_TASKS A
          WHERE A.NAME LIKE DECODE(IN_NAME, 
                                   TO_CHAR(DBMS_ADVISOR.ADVISOR_ALL), '%', 
                                   IN_NAME)
            AND A.OWNER# = IN_OWNER
            AND BITAND(A.PROPERTY,IN_PROP) = IN_PROP;
  BEGIN
    IF PROP IS NULL OR PROP = 0 THEN
      L_PROP := TASK_PROP_TASK;
    ELSE
      L_PROP := PROP;
    END IF;
    IF (INSTR(TASK_NAME, '%') > 0 OR 
        TASK_NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_ALL)) 
    THEN 
      IF (LENGTH(TASK_NAME) > 30) THEN
        RAISE_TASK_NAME_ERROR(TASK_NAME, L_PROP);
      END IF;
      L_USER_ID := SYS_CONTEXT('USERENV', 'SESSION_USERID');
      BIT_EXCLUSIONS := TASK_PROP_READONLY + TASK_PROP_TEMPLATE;
      OPEN TASK_CUR(TASK_NAME, L_PROP, L_USER_ID);
      LOOP
        FETCH TASK_CUR INTO TASK_ID,A_PROP;
        EXIT WHEN TASK_CUR%NOTFOUND;
        IF BITAND(A_PROP,BIT_EXCLUSIONS) = 0 THEN
          COMMON_DELETE_TASK(TASK_ID);
        END IF;
      END LOOP;
      CLOSE TASK_CUR;
    ELSE
      TASK_ID := VALIDATE_TASK(TASK_NAME, L_PROP);
      CHECK_MODIFY(TASK_NAME, TASK_ID);
      COMMON_DELETE_TASK(TASK_ID);
    END IF;
    COMMIT;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        RAISE;
    RETURN;
  END DELETE_TASK;
PROCEDURE DELETE_USER_TASKS(USER_NAME   IN VARCHAR2)
  IS
    TASK_ID   BINARY_INTEGER;
    USERID    BINARY_INTEGER;
    CURSOR TASKS_CUR(OWNER_NAME VARCHAR2) IS
      SELECT TASK_ID FROM SYS.DBA_ADVISOR_TASKS
      WHERE OWNER = OWNER_NAME;
  BEGIN
     USERID := VALIDATE_USERNAME(USER_NAME);
     OPEN TASKS_CUR(USER_NAME);
     LOOP
       FETCH TASKS_CUR INTO TASK_ID;
       EXIT WHEN TASKS_CUR%NOTFOUND;
       COMMON_DELETE_TASK(TASK_ID_NUM    => TASK_ID, 
                          DELETE_OPTIONS => DEL_OPT_NO_STATS);
     END LOOP;
     CLOSE TASKS_CUR;
  EXCEPTION
     WHEN OTHERS THEN
        NULL;
  END DELETE_USER_TASKS;
FUNCTION COMMON_EXECUTE_TASK(
  TASK_NAME             IN VARCHAR2,
  TASK_OPERATION        IN BINARY_INTEGER         := TASK_EXECUTE, 
  EXECUTION_TYPE        IN VARCHAR2               := NULL,
  EXECUTION_NAME        IN VARCHAR2               := NULL,
  EXECUTION_DESC        IN VARCHAR2               := NULL,
  EXECUTION_PARAMS      IN DBMS_ADVISOR.ARGLIST   := NULL)
RETURN VARCHAR2
  IS
    L_STATUS            BINARY_INTEGER;
    TP                  WRI$_ADV_ABSTRACT_T;
    FLAGS               BINARY_INTEGER;    
    TASK_NUM            BINARY_INTEGER  := NULL;
    EXEC_ID             NUMBER          := NULL;
    EXEC_NAME           VARCHAR2(32767) := EXECUTION_NAME; 
    ETYPE               VARCHAR2(32767) := EXECUTION_TYPE; 
    ETYPE#              BINARY_INTEGER; 
    PRIOR_NUM_OBJECTS   NUMBER;
    START_TIME          DATE;
    TASK_STORED_PROP    NUMBER;
    GATHER_STATS        BOOLEAN;
  BEGIN
    GATHER_STATS := FALSE;
    TASK_NUM := VALIDATE_TASK(TASK_NAME);
    TP := FETCH_ADVISOR(TASK_NUM);
    SELECT PROPERTY INTO FLAGS FROM SYS.WRI$_ADV_DEFINITIONS
    WHERE ID = TP.ADVISOR_ID;
    IF (TASK_OPERATION = TASK_RESUME AND BITAND(FLAGS, ADV_PROP_RESUMABLE) = 0)
    THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOT_SUPPORTED);
    END IF;
    CHECK_TEMPLATE(TASK_NAME, TASK_NUM);
    CHECK_MODIFY(TASK_NAME, TASK_NUM);
    SELECT STATUS# INTO L_STATUS
    FROM SYS.DBA_ADVISOR_TASKS
    WHERE TASK_ID = TASK_NUM
    FOR UPDATE;
    IF (L_STATUS = TASK_STATE_EXEC) THEN 
      HANDLE_LOCK(TASK_NUM, TASK_LOCK_X, 0);
      RECOVER_SINGLE_STALE_TASK(TASK_NUM);
      L_STATUS := TASK_STATE_ERROR; 
      HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
    END IF; 
    IF (BITAND(FLAGS, ADV_PROP_MULTI_EXEC) = 0) THEN 
      CASE L_STATUS
        WHEN TASK_STATE_COMPLETED THEN
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXEC_RESULTS, TASK_NAME);
        WHEN TASK_STATE_ERROR THEN
          IF (TASK_OPERATION <> TASK_RESUME OR            
              BITAND(FLAGS, ADV_PROP_RESUME_FATALER) = 0) 
          THEN
            DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ERR_CANCEL_EXISTS, TASK_NAME);
          END IF; 
        WHEN TASK_STATE_CANCELLED THEN
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ERR_CANCEL_EXISTS, TASK_NAME);
        WHEN TASK_STATE_INTERRUPTED THEN
          IF (TASK_OPERATION = TASK_EXECUTE) THEN
            DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INTR_EXISTS, TASK_NAME);
          END IF;
        ELSE
          NULL;   
      END CASE;
    END IF; 
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X_TO_S, 2);
    SELECT PROPERTY INTO TASK_STORED_PROP
    FROM WRI$_ADV_TASKS
    WHERE ID = TASK_NUM;    
    IF (BITAND(TASK_STORED_PROP, TASK_PROP_SYSTEMTASK) = 0 AND 
        BITAND(FLAGS, ADV_PROP_GATHER_STATS) <> 0) THEN
      GET_GATHER_STATS_INFO(PRIOR_NUM_OBJECTS, START_TIME, TASK_NUM);
    END IF;
    IF (TASK_OPERATION = TASK_EXECUTE OR L_STATUS = TASK_STATE_INITIAL) THEN
      SELECT WRI$_ADV_SEQ_EXEC.NEXTVAL
      INTO   EXEC_ID
      FROM   DUAL;
      IF ((EXEC_NAME IS NOT NULL AND EXECUTION_EXISTS(EXEC_NAME, TASK_NUM)) OR
          (EXEC_NAME IS NULL AND NOT 
           GENERATE_UNIQUE_NAME(TARGET_TYPE => 'EXECUTION', 
                                TARGET_PREFIX => 'EXEC', 
                                TARGET_ID => TASK_NUM,
                                TARGET_SUB_ID => EXEC_ID, 
                                NEW_NAME => EXEC_NAME)))
      THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXEC_ALREADY_EXISTS, EXEC_NAME);
      END IF; 
      VALIDATE_EXECUTION_TYPE(TP.ADVISOR_ID, FLAGS, TASK_NUM, ETYPE, ETYPE#); 
      INSERT INTO SYS.WRI$_ADV_EXECUTIONS 
        (TASK_ID, ID, NAME, DESCRIPTION, 
         EXEC_TYPE, EXEC_TYPE_ID, EXEC_START, EXEC_MTIME, 
         STATUS, STATUS_MSG_ID, ERROR_MSG_ID, ADVISOR_ID)
      VALUES
        (TASK_NUM, EXEC_ID, EXEC_NAME, 
         SUBSTR(EXECUTION_DESC, 1, 256), 
         ETYPE, ETYPE#, SYSDATE, SYSDATE, 
         TASK_STATE_EXEC, 0, 0, TP.ADVISOR_ID);
      SET_EXECUTION_PARAMS(TP, FLAGS, 
                           TASK_NAME, TASK_NUM, 
                           TASK_STATE_INITIAL,   
                           EXEC_NAME, EXECUTION_PARAMS); 
      UPDATE_TASK(TASK_ID => TASK_NUM, 
                  LAST_EXECUTION => EXEC_NAME, 
                  NEW_STATUS => 0, 
                  NEW_CLEANUP => 1,
                  DB_VERSION => GET_DB_VERSION); 
      COMMIT; 
      COMMON_SUB_EXECUTE(TP, TASK_NUM, TASK_EXECUTE);      
    ELSIF (TASK_OPERATION = TASK_RESUME) THEN
      IF (L_STATUS = TASK_STATE_ERROR AND           
          BITAND(FLAGS, ADV_PROP_RESUME_FATALER) = 0) 
      THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ERR_CANCEL_EXISTS, TASK_NAME);
      END IF; 
      EXEC_NAME := GET_LAST_EXECUTION(TASK_NUM);
      UPDATE_EXECUTION(TASK_NUM, EXEC_NAME, TASK_STATE_EXEC);
      UPDATE_TASK(TASK_ID => TASK_NUM, NEW_CLEANUP => 1);
      COMMIT; 
      COMMON_SUB_EXECUTE(TP, TASK_NUM, TASK_RESUME); 
    END IF;
    IF (BITAND(TASK_STORED_PROP, TASK_PROP_SYSTEMTASK) = 0 AND
        BITAND(FLAGS, ADV_PROP_GATHER_STATS) <> 0) THEN
          GATHER_STATS := DECIDE_GATHER_STATS(PRIOR_NUM_OBJECTS => PRIOR_NUM_OBJECTS,
                                              START_TIME        => START_TIME,
                                              TASK_ID           => TASK_NUM,
                                              OPERATION_TYPE    => STATS_OPER_EXECUTE);
    END IF;
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X_TO_R);
    IF (GATHER_STATS) THEN
      GATHER_STATISTICS();
    END IF;
    RETURN EXEC_NAME;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK; 
        IF (TASK_NUM IS NOT NULL) THEN 
         IF(SQLCODE IN (USER_INTERRUPT, TO_INTERRUPT, WAIT_INTERRUPT)) THEN
            HANDLE_LOCK(TASK_NUM, TASK_LOCK_X_TO_R); 
          ELSE
            HANDLE_LOCK(TASK_NUM, TASK_LOCK_R, 2);
          END IF;
        END IF; 
        RAISE; 
END COMMON_EXECUTE_TASK;
FUNCTION TEST_CHECK_INTERRUPT (TASK_ID IN BINARY_INTEGER,
                               TEST_ID IN BINARY_INTEGER,
                               RAISE_ERROR IN BINARY_INTEGER)
  RETURN BINARY_INTEGER
  IS
  EXTERNAL
  NAME "keautcintrPLSQL"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   TASK_ID UB4,
   TEST_ID UB4,
   RAISE_ERROR UB4,
   RETURN
  );
PROCEDURE TEST_EXECUTE_TASK (TASK_NAME       IN VARCHAR2,
                             TEST_ID         IN BINARY_INTEGER,
                             RAISE_ERROR     IN BINARY_INTEGER)
  IS
    TASK_NUM BINARY_INTEGER := 0;
    ERR_NUM BINARY_INTEGER := 0;
    TP SYS.WRI$_ADV_ABSTRACT_T;
    L_STATUS BINARY_INTEGER;
    EXEC_NAME VARCHAR2(30); 
  BEGIN
    TASK_NUM := VALIDATE_TASK (TASK_NAME);
    TP := FETCH_ADVISOR(TASK_NUM);
    CHECK_TEMPLATE(TASK_NAME, TASK_NUM);
    CHECK_MODIFY(TASK_NAME, TASK_NUM);
    SELECT STATUS#, LAST_EXECUTION INTO L_STATUS, EXEC_NAME
    FROM SYS.DBA_ADVISOR_TASKS
    WHERE TASK_ID = TASK_NUM
    FOR UPDATE;
    IF L_STATUS = TASK_STATE_COMPLETED THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXEC_RESULTS,
                                        TASK_NAME);
    END IF;
    IF L_STATUS = TASK_STATE_INTERRUPTED THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INTR_EXISTS,
                                        TASK_NAME);
    END IF;
    IF L_STATUS = TASK_STATE_ERROR OR
       L_STATUS = TASK_STATE_CANCELLED THEN
       DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(
                         ERR_CANCEL_EXISTS, TASK_NAME);
    END IF;
    IF L_STATUS = TASK_STATE_EXEC THEN
      UPDATE SYS.WRI$_ADV_EXECUTIONS
        SET STATUS = TASK_STATE_ERROR
        WHERE TASK_ID = TASK_NUM AND NAME = EXEC_NAME;
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(
                         ERR_CANCEL_EXISTS, TASK_NAME);
    END IF;
    UPDATE SYS.WRI$_ADV_EXECUTIONS
      SET STATUS = TASK_STATE_EXEC,
          EXEC_START = SYSDATE
      WHERE TASK_ID = TASK_NUM AND NAME = EXEC_NAME;
    UPDATE SYS.WRI$_ADV_TASKS
      SET CLEANUP = 1
      WHERE ID = TASK_NUM AND NAME = EXEC_NAME;
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X_TO_S, 2);
    COMMIT;
    ERR_NUM := TEST_CHECK_INTERRUPT(TASK_NUM, TEST_ID, RAISE_ERROR);
    ERR_NUM := NVL(ERR_NUM, 0);
    IF     ERR_NUM = 0 OR
           ERR_NUM = (-1 * USER_INTERRUPT) OR
           ERR_NUM = (-1 * TO_INTERRUPT) THEN
      COMMIT;
    ELSE
      ROLLBACK;
    END IF;
    UPDATE SYS.WRI$_ADV_EXECUTIONS
      SET STATUS = DECODE(ERR_NUM,
                          0,
                          DECODE (STATUS,
                                  TASK_STATE_EXEC,
                                  TASK_STATE_COMPLETED,
                                  STATUS),
                          -1 * USER_CANCEL,
                          TASK_STATE_CANCELLED,
                          -1 * TO_CANCEL,
                          TASK_STATE_CANCELLED,
                          -1 * USER_INTERRUPT,
                          TASK_STATE_INTERRUPTED,
                          -1 * TO_INTERRUPT,
                          TASK_STATE_INTERRUPTED,
                          TASK_STATE_ERROR),
          EXEC_END = SYSDATE
      WHERE TASK_ID = TASK_NUM AND NAME = EXEC_NAME;
    IF ERR_NUM > 0 THEN
       RECORD_ERRORMSG(TASK_NUM, EXEC_NAME, ERR_NUM);
    END IF;
    COMMIT;
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X_TO_R);
    RETURN;
    EXCEPTION
     WHEN OTHERS THEN
       ROLLBACK;
       SELECT COUNT(*) INTO L_STATUS FROM SYS.DBA_ADVISOR_TASKS
        WHERE TASK_ID = TASK_NUM;
       IF L_STATUS > 0 THEN
          UPDATE SYS.WRI$_ADV_EXECUTIONS
            SET STATUS = TASK_STATE_ERROR,
                EXEC_END = SYSDATE
            WHERE TASK_ID = TASK_NUM AND NAME = EXEC_NAME;
         RECORD_ERRORMSG(TASK_NUM, EXEC_NAME, 0);
       END IF;
       UPDATE_TASK(TASK_NUM);
       COMMIT;
       HANDLE_LOCK(TASK_NUM, TASK_LOCK_R, 2);
       RAISE;
  END TEST_EXECUTE_TASK;
PROCEDURE GET_REC_ATTRIBUTES (TASK_NAME            IN VARCHAR2,
                              RECOM_ID             IN NUMBER,
                              ACTION_ID            IN NUMBER,
                              ATTRIBUTE_NAME       IN VARCHAR2,
                              VALUE                OUT VARCHAR2,
                              OWNER_NAME           IN VARCHAR2)
  IS
    TASK_ID_NUM BINARY_INTEGER := 0;
    L_CNT BINARY_INTEGER;
    TP SYS.WRI$_ADV_ABSTRACT_T;
    L_OWNER_ID BINARY_INTEGER;
  BEGIN
    L_OWNER_ID := VALIDATE_USERNAME(OWNER_NAME);
    TASK_ID_NUM := VALIDATE_TASK(TASK_NAME, 0, L_OWNER_ID);
    TP := FETCH_ADVISOR(TASK_ID_NUM);
    CHECK_EXECUTION_STATUS(TASK_NAME, TASK_ID_NUM);
    IF ATTRIBUTE_NAME IS NULL THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'ATTRIBUTE_NAME');
    END IF;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_X);
    IF TP.ADVISOR_ID = 2 AND ACTION_ID = 0 THEN
      SELECT COUNT(*) INTO L_CNT
        FROM SYS.WRI$_ADV_REC_ACTIONS A
        WHERE A.REC_ID = RECOM_ID
          AND A.TASK_ID = TASK_ID_NUM;
    ELSE
      SELECT COUNT(*) INTO L_CNT
        FROM SYS.WRI$_ADV_REC_ACTIONS A
        WHERE A.ACT_ID = ACTION_ID
          AND A.REC_ID = RECOM_ID
          AND A.TASK_ID = TASK_ID_NUM;
    END IF;
    IF L_CNT = 0 THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INVALID_REC,
                                        TO_CHAR(RECOM_ID),TO_CHAR(ACTION_ID),
                                        TASK_NAME);
    END IF;
    TP.SUB_GET_REC_ATTR (TASK_ID_NUM, 
                         RECOM_ID,ACTION_ID, 
                         UPPER(ATTRIBUTE_NAME), 
                         VALUE);
    COMMIT;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
    RETURN;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
      HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
      RAISE;
  END GET_REC_ATTRIBUTES;
FUNCTION GET_TASK_REPORT(TASK_NAME      IN VARCHAR2,
                         TYPE           IN VARCHAR2,
                         LEVEL          IN VARCHAR2,
                         SECTION        IN VARCHAR2,
                         OWNER_NAME     IN VARCHAR2,
                         EXECUTION_NAME IN VARCHAR2 := NULL,
                         OBJECT_ID      IN NUMBER   := NULL)
RETURN CLOB
  IS
    TASK_NUM BINARY_INTEGER := 0;
    L_CNT BINARY_INTEGER;
    L_OWNER_ID BINARY_INTEGER;
    TP SYS.WRI$_ADV_ABSTRACT_T;
    L_BUFFER CLOB;
    EXEC_NAME VARCHAR2(32767) := EXECUTION_NAME; 
    FLAGS BINARY_INTEGER;
  BEGIN
    IF TYPE IS NOT NULL AND UPPER(TYPE) != 'TEXT' THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'TYPE');
    END IF;
    IF LEVEL IS NOT NULL AND UPPER(LEVEL) NOT IN ('BASIC','TYPICAL','ALL') THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'LEVEL');
    END IF;
    L_OWNER_ID := VALIDATE_USERNAME(OWNER_NAME);
    TASK_NUM := VALIDATE_TASK(TASK_NAME, 0, L_OWNER_ID);
    TP := FETCH_ADVISOR(TASK_NUM);
    SELECT PROPERTY INTO FLAGS FROM SYS.WRI$_ADV_DEFINITIONS
      WHERE ID = TP.ADVISOR_ID;
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X);
    CHECK_EXECUTION_STATUS(TASK_NAME, TASK_NUM, EXECUTION_NAME);
    EXEC_NAME := VALIDATE_EXECUTION_OBJECT(TASK_NAME, TASK_NUM, 
                                           EXEC_NAME, OBJECT_ID);
    L_BUFFER := ' ';
    IF (BITAND(FLAGS, ADV_PROP_MULTI_EXEC) <> 0 OR OBJECT_ID IS NOT NULL) THEN 
      TP.SUB_GET_REPORT(TASK_NUM,  
                        NVL(UPPER(TYPE), 'TEXT'), 
                        NVL(UPPER(LEVEL), 'TYPICAL'), 
                        NVL(UPPER(SECTION), 'ALL'), 
                        L_BUFFER, 
                        EXEC_NAME, 
                        OBJECT_ID);
    ELSE 
      TP.SUB_GET_REPORT(TASK_NUM,  
                        NVL(UPPER(TYPE), 'TEXT'), 
                        NVL(UPPER(LEVEL), 'TYPICAL'), 
                        NVL(UPPER(SECTION), 'ALL'), 
                        L_BUFFER);
    END IF; 
    IF (BITAND(FLAGS, ADV_PROP_MANUAL_REPT_FUSG) = 0) THEN
      TRACK_REPORT_USAGE(TP.ADVISOR_ID);
    END IF;
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
    RETURN (L_BUFFER);
    EXCEPTION
      WHEN OTHERS THEN
        HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
        RAISE;
  END GET_TASK_REPORT;
FUNCTION GET_TASK_SCRIPT (TASK_NAME      IN VARCHAR2,
                          TYPE           IN VARCHAR2,
                          REC_ID         IN NUMBER,
                          ACT_ID         IN NUMBER,
                          OWNER_NAME     IN VARCHAR2 := NULL,
                          EXECUTION_NAME IN VARCHAR2 := NULL,
                          OBJECT_ID      IN NUMBER   := NULL)
  RETURN CLOB
  IS
    TASK_NUM BINARY_INTEGER := 0;
    L_REC_ID BINARY_INTEGER;
    L_ACT_ID BINARY_INTEGER;
    L_CNT BINARY_INTEGER;
    L_BUFFER CLOB;
    TP SYS.WRI$_ADV_ABSTRACT_T;
    L_OWNER_ID BINARY_INTEGER;
    E_NAME VARCHAR2(32767) := EXECUTION_NAME;
    FLAGS BINARY_INTEGER; 
  BEGIN
    L_OWNER_ID := VALIDATE_USERNAME(OWNER_NAME);
    TASK_NUM := VALIDATE_TASK(TASK_NAME, 0, L_OWNER_ID);
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X);
    CHECK_EXECUTION_STATUS(TASK_NAME, TASK_NUM, EXECUTION_NAME);
    E_NAME := VALIDATE_EXECUTION_OBJECT(TASK_NAME, TASK_NUM, 
                                        E_NAME, OBJECT_ID);
    IF REC_ID IS NULL OR REC_ID = DBMS_ADVISOR.ADVISOR_ALL THEN
      L_REC_ID := 0;
    ELSE
      L_REC_ID := REC_ID;
    END IF;
    IF ACT_ID IS NULL OR ACT_ID = DBMS_ADVISOR.ADVISOR_ALL THEN
      L_ACT_ID := 0;
    ELSE
      L_ACT_ID := ACT_ID;
    END IF;
    IF L_REC_ID > 0 OR L_ACT_ID > 0 THEN
      SELECT COUNT(*) INTO L_CNT FROM SYS.WRI$_ADV_RECOMMENDATIONS
        WHERE TASK_ID = TASK_NUM AND ID = L_REC_ID AND 
              NVL(EXEC_NAME, E_NAME) = E_NAME;
      IF L_CNT = 0 THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_RECOMM,
                                          TO_CHAR(L_REC_ID), TASK_NAME);
      END IF;
      IF L_ACT_ID > 0 THEN
        SELECT COUNT(*) INTO L_CNT
          FROM SYS.WRI$_ADV_REC_ACTIONS A
         WHERE A.ACT_ID = L_ACT_ID
          AND A.REC_ID = L_REC_ID
          AND A.TASK_ID = TASK_NUM;
        IF L_CNT = 0 THEN
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INVALID_REC,
                                            TO_CHAR(L_REC_ID),
                                            TO_CHAR(L_ACT_ID),
                                            TASK_NAME);
        END IF;
      END IF;
    END IF;
    IF TYPE IS NOT NULL AND UPPER(TYPE) NOT IN ('UNDO','IMPLEMENTATION') THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'TYPE');
    END IF;
    TP := FETCH_ADVISOR(TASK_NUM);
    SELECT PROPERTY INTO FLAGS FROM SYS.WRI$_ADV_DEFINITIONS
      WHERE ID = TP.ADVISOR_ID;
    L_BUFFER := ' ';
    IF (BITAND(FLAGS, ADV_PROP_MULTI_EXEC) <> 0 OR OBJECT_ID IS NOT NULL) THEN 
      TP.SUB_GET_SCRIPT(TASK_NUM, 
                        NVL(UPPER(TYPE), 'IMPLEMENTATION'), 
                        L_BUFFER, 
                        L_REC_ID, 
                        L_ACT_ID, 
                        E_NAME, 
                        OBJECT_ID);
    ELSE
      TP.SUB_GET_SCRIPT(TASK_NUM, 
                        NVL(UPPER(TYPE), 'IMPLEMENTATION'), 
                        L_BUFFER, 
                        L_REC_ID, 
                        L_ACT_ID);
    END IF; 
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
    RETURN(L_BUFFER);
    EXCEPTION
      WHEN OTHERS THEN
        HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
        RAISE;
  END GET_TASK_SCRIPT;
FUNCTION VALIDATE_USERNAME(USER_NAME IN VARCHAR2)
  RETURN NUMBER
  IS
    L_USER_ID NUMBER;
  BEGIN
    IF (USER_NAME IS NULL OR LENGTH(USER_NAME) = 0) THEN
       L_USER_ID := SYS_CONTEXT('USERENV', 'SESSION_USERID');
    ELSE
       SELECT USER# INTO L_USER_ID FROM USER$ WHERE NAME = USER_NAME;
    END IF;
    RETURN L_USER_ID;
  EXCEPTION 
    WHEN NO_DATA_FOUND THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_USER, ADJUST_STRING(USER_NAME, 30));
    WHEN OTHERS THEN RAISE; 
  END VALIDATE_USERNAME;
PROCEDURE IMPLEMENT_TASK (TASK_NAME       IN VARCHAR2,
                          REC_ID          IN NUMBER,
                          EXIT_ON_ERROR   IN BOOLEAN)
  IS
    TASK_NUM BINARY_INTEGER := 0;
    TP SYS.WRI$_ADV_ABSTRACT_T;
    L_CNT BINARY_INTEGER;
    L_REC_ID BINARY_INTEGER := 0;
    L_EXIT BINARY_INTEGER := 0;
  BEGIN
    TASK_NUM := VALIDATE_TASK(TASK_NAME);
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X);
    CHECK_MODIFY(TASK_NAME, TASK_NUM);
    CHECK_EXECUTION_STATUS(TASK_NAME, TASK_NUM);
    IF REC_ID IS NOT NULL THEN
      L_REC_ID := REC_ID;
      IF EXIT_ON_ERROR IS NULL THEN
        L_EXIT := 0;
      ELSIF EXIT_ON_ERROR THEN
        L_EXIT := 1;
      ELSE
        L_EXIT := 2;
      END IF;
      SELECT COUNT(*) INTO L_CNT FROM SYS.WRI$_ADV_RECOMMENDATIONS
        WHERE TASK_ID = TASK_NUM AND ID = L_REC_ID;
      IF L_CNT = 0 THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_RECOMM,
                                          TO_CHAR(L_REC_ID), TASK_NAME);
      END IF;
    END IF;
    TP := FETCH_ADVISOR(TASK_NUM);
    IF L_REC_ID > 0 THEN
      TP.SUB_IMPLEMENT(TASK_NUM, L_REC_ID, L_EXIT);
    ELSE
      TP.SUB_IMPLEMENT(TASK_NUM);
    END IF;
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
    RETURN;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
      RAISE;
  END IMPLEMENT_TASK;
PROCEDURE INTERRUPT_TASK(TASK_NAME       IN VARCHAR2)
  IS
    STATUS_VALUE BINARY_INTEGER;
    L_ID BINARY_INTEGER := 0;
    EXEC_NAME VARCHAR2(30);
  BEGIN
    L_ID := VALIDATE_TASK(TASK_NAME);
    SELECT A.STATUS#, A.LAST_EXECUTION INTO STATUS_VALUE, EXEC_NAME
    FROM SYS.DBA_ADVISOR_TASKS A
    WHERE A.TASK_ID = L_ID
    FOR UPDATE;
    IF STATUS_VALUE != TASK_STATE_EXEC THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOT_EXECUTING, TASK_NAME);
    END IF;
    UPDATE WRI$_ADV_EXECUTIONS A
      SET A.STATUS = TASK_STATE_INTERRUPTED
    WHERE A.TASK_ID = L_ID AND A.NAME = EXEC_NAME;
    SIGNAL_INTERRUPT(L_ID, TASK_INTR_I);
    COMMIT;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
      RAISE;
    RETURN;
  END INTERRUPT_TASK;
PROCEDURE MARK_RECOMMENDATION (TASK_NAME       IN VARCHAR2,
                               ID              IN NUMBER,
                               ACTION          IN VARCHAR2)
  IS
    TASK_NUM BINARY_INTEGER := 0;
    L_ACTION_ID BINARY_INTEGER := 0;
    L_ID BINARY_INTEGER;
    L_CNT BINARY_INTEGER;
  BEGIN
    L_ID := ID;
    TASK_NUM := VALIDATE_TASK(TASK_NAME);
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X);
    CHECK_MODIFY(TASK_NAME, TASK_NUM);
    CASE UPPER(ACTION)
      WHEN 'ACCEPT' THEN
        L_ACTION_ID := 1;
      WHEN 'REJECT' THEN
        L_ACTION_ID := 2;
      WHEN 'IGNORE' THEN
        L_ACTION_ID := 3;
      WHEN 'IMPLEMENTED' THEN
        L_ACTION_ID := 4;
      ELSE 
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ANNOT);
    END CASE; 
    IF ID = DBMS_ADVISOR.ADVISOR_ALL THEN
      UPDATE SYS.WRI$_ADV_RECOMMENDATIONS
         SET ANNOTATION = L_ACTION_ID
        WHERE TASK_ID = TASK_NUM;
    ELSE
      SELECT COUNT(*) INTO L_CNT FROM SYS.WRI$_ADV_RECOMMENDATIONS
        WHERE TASK_ID = TASK_NUM AND ID = L_ID;
      IF L_CNT = 0 THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_RECOMM, TO_CHAR(ID), TASK_NAME);
      END IF;
      UPDATE SYS.WRI$_ADV_RECOMMENDATIONS
         SET ANNOTATION = L_ACTION_ID
        WHERE TASK_ID = TASK_NUM
          AND ID = L_ID;
    END IF;
    UPDATE_TASK(TASK_NUM);
    COMMIT;
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
    RETURN;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
      RAISE;
  END MARK_RECOMMENDATION;
PROCEDURE QUICK_TUNE (ADVISOR_NAME           IN VARCHAR2,
                      TASK_NAME              IN VARCHAR2,
                      ATTR1                  IN CLOB,
                      ATTR2                  IN VARCHAR2,
                      ATTR3                  IN NUMBER,
                      TEMPLATE               IN VARCHAR2,
                      IMPLEMENT              IN BOOLEAN,
                      DESCR                  IN VARCHAR2)
  IS
    TP SYS.WRI$_ADV_ABSTRACT_T;
  BEGIN
    TP := VALIDATE_ADVISOR(ADVISOR_NAME);
    PARSE_NAME(TASK_NAME, TASK_PROP_TASK);
    TP.SUB_QUICK_TUNE(TASK_NAME, ATTR1, ATTR2, ATTR3, TEMPLATE, IMPLEMENT);
    IF DESCR IS NOT NULL THEN
      UPDATE SYS.WRI$_ADV_TASKS
      SET DESCRIPTION = DESCR
      WHERE ADVISOR_ID = TP.ADVISOR_ID AND 
            NAME = TASK_NAME AND 
            BITAND(PROPERTY,4) = 4;
      COMMIT;
    END IF;
    RETURN;
  END QUICK_TUNE;
PROCEDURE RESET_TASK (TASK_NUM  IN BINARY_INTEGER)
  IS
  L_PROP BINARY_INTEGER;
  FLAGS  BINARY_INTEGER;
  PRIOR_NUM_OBJECTS NUMBER;
  START_TIME DATE;
  GATHER_STATS BOOLEAN;
BEGIN
  GATHER_STATS := FALSE;
  SELECT D.PROPERTY INTO FLAGS 
  FROM SYS.WRI$_ADV_TASKS T, SYS.WRI$_ADV_DEFINITIONS D
  WHERE T.ID = TASK_NUM AND D.ID = T.ADVISOR_ID;  
  HANDLE_LOCK(TASK_NUM, TASK_LOCK_X);
  COMMON_CLEANUP_TASK(TASK_NUM);
  IF (BITAND(FLAGS, ADV_PROP_GATHER_STATS) <> 0) THEN
    GET_GATHER_STATS_INFO(PRIOR_NUM_OBJECTS, START_TIME, TASK_NUM);
  END IF;
  COMMON_RESET_TASK(TASK_NUM);
  COMMIT;
  IF (BITAND(FLAGS, ADV_PROP_GATHER_STATS) <> 0) THEN
    GATHER_STATS := DECIDE_GATHER_STATS(PRIOR_NUM_OBJECTS => PRIOR_NUM_OBJECTS,
                                        START_TIME        => START_TIME,
                                        TASK_ID           => TASK_NUM,
                                        OPERATION_TYPE    => STATS_OPER_DELETE);
  END IF;
  HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
  IF (GATHER_STATS) THEN
    GATHER_STATISTICS();
  END IF;
  RETURN;
  EXCEPTION
    WHEN OTHERS THEN
      ROLLBACK;
      HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
    RAISE;
END RESET_TASK;
PROCEDURE RESET_TASK(TASK_NAME       IN VARCHAR2,
                     PROP            IN BINARY_INTEGER)
  IS
    TASK_NUM BINARY_INTEGER := 0;
    L_PROP BINARY_INTEGER;
    FLAGS BINARY_INTEGER;
    GATHER_STATS BOOLEAN;
    PRIOR_NUM_OBJECTS NUMBER;
    START_TIME DATE;
  BEGIN
    IF PROP IS NULL OR PROP = 0 THEN
      L_PROP := TASK_PROP_TASK;
    ELSE
      L_PROP := PROP;
    END IF;
    TASK_NUM := VALIDATE_TASK(TASK_NAME, L_PROP);
    GATHER_STATS := FALSE;
    SELECT D.PROPERTY INTO FLAGS 
    FROM SYS.WRI$_ADV_TASKS T, SYS.WRI$_ADV_DEFINITIONS D
    WHERE T.ID = TASK_NUM AND D.ID = T.ADVISOR_ID;  
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_X);
    CHECK_MODIFY(TASK_NAME, TASK_NUM);
    COMMON_CLEANUP_TASK(TASK_NUM);
    IF (BITAND(FLAGS, ADV_PROP_GATHER_STATS) <> 0) THEN
      GET_GATHER_STATS_INFO(PRIOR_NUM_OBJECTS, START_TIME, TASK_NUM);
    END IF;
    COMMON_RESET_TASK(TASK_NUM);
    COMMIT;
    IF (BITAND(FLAGS, ADV_PROP_GATHER_STATS) <> 0) THEN
      GATHER_STATS := DECIDE_GATHER_STATS(PRIOR_NUM_OBJECTS => PRIOR_NUM_OBJECTS,
                                          START_TIME        => START_TIME,
                                          TASK_ID           => TASK_NUM,
                                          OPERATION_TYPE    => STATS_OPER_DELETE);
    END IF;
    HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
    IF (GATHER_STATS) THEN
      GATHER_STATISTICS();
    END IF;
    RETURN;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        HANDLE_LOCK(TASK_NUM, TASK_LOCK_R);
      RAISE;
  END RESET_TASK;
PROCEDURE SET_TASK_PARAMETER(
  TASK_NAME     IN VARCHAR2,
  PARAMETER     IN VARCHAR2,
  DATA          IN VARCHAR2,
  PROP          IN BINARY_INTEGER := 0,
  SCOPE         IN BINARY_INTEGER := FUTURE_EXECUTIONS,
  TASK_OWNER_ID IN BINARY_INTEGER := -1)
  IS
    TASK_ID_NUM BINARY_INTEGER := 0;
    TP SYS.WRI$_ADV_ABSTRACT_T;
    L_DATA VARCHAR2(32767) := DATA;
    L_NAME VARCHAR2(32767) := PARAMETER;
    ADV_PROP BINARY_INTEGER;
    TASK_PROP BINARY_INTEGER;
    L_NEW_FLAGS BINARY_INTEGER := 0;
    TASK_STATUS BINARY_INTEGER;
    TASK_STORED_PROP NUMBER;              
    L_DEFAULTED BOOLEAN := FALSE;
    ENAME VARCHAR2(30);
    L_DATATYPE NUMBER;
    L_DESCRIPTION VARCHAR2(9);
  BEGIN
    IF PROP IS NULL OR PROP = 0 THEN
      TASK_PROP := TASK_PROP_TASK;
    ELSE
      TASK_PROP := PROP;
    END IF;
    TASK_ID_NUM := VALIDATE_TASK(TASK_NAME, TASK_PROP, TASK_OWNER_ID);
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_X);
    CHECK_MODIFY(TASK_NAME, TASK_ID_NUM);
    TP := FETCH_ADVISOR(TASK_ID_NUM);
    SELECT PROPERTY INTO ADV_PROP 
      FROM SYS.WRI$_ADV_DEFINITIONS
      WHERE ID = TP.ADVISOR_ID;
    SELECT NVL(E.STATUS, A.STATUS) STATUS#, A.PROPERTY 
    INTO TASK_STATUS, TASK_STORED_PROP
    FROM WRI$_ADV_TASKS A, WRI$_ADV_EXECUTIONS E 
    WHERE A.ID = E.TASK_ID(+) AND A.ADVISOR_ID = E.ADVISOR_ID(+) AND
          A.LAST_EXEC_NAME = E.NAME(+) AND A.ID = TASK_ID_NUM;
    VALIDATE_TASK_PARAMETER(TP, ADV_PROP, TASK_NAME, TASK_ID_NUM, TASK_STATUS, 
                            TASK_STORED_PROP, SCOPE, L_NAME, L_DATA, 
                            L_NEW_FLAGS); 
    IF (SCOPE = FUTURE_EXECUTIONS) THEN
      IF (BITAND(ADV_PROP, ADV_PROP_MULTI_EXEC) <> 0) THEN
        PROPAGATE_TASK_PARAMETER(TASK_ID_NUM, L_NAME, TP.ADVISOR_ID);
      END IF;
      SELECT A.DATATYPE, A.DESCRIPTION 
        INTO L_DATATYPE, L_DESCRIPTION 
        FROM SYS.WRI$_ADV_DEF_PARAMETERS A
        WHERE A.NAME = L_NAME
          AND (A.ADVISOR_ID = TP.ADVISOR_ID
            OR A.ADVISOR_ID = 0);
      MERGE INTO WRI$_ADV_PARAMETERS P
      USING (SELECT TASK_ID_NUM TASK_ID, L_NAME NAME, L_DATA VALUE, 
                    L_DATATYPE DATATYPE, L_NEW_FLAGS FLAGS,
                    L_DESCRIPTION DESCRIPTION 
             FROM DUAL) I
      ON     (P.TASK_ID = I.TASK_ID AND P.NAME = I.NAME)
      WHEN MATCHED THEN
        UPDATE SET P.VALUE = I.VALUE,
                   P.FLAGS = I.FLAGS
               WHERE P.VALUE <> I.VALUE
      WHEN NOT MATCHED THEN
        INSERT(TASK_ID, NAME, VALUE, DATATYPE, FLAGS, DESCRIPTION)
        VALUES(I.TASK_ID, I.NAME, I.VALUE, I.DATATYPE, 
               I.FLAGS, I.DESCRIPTION);
    ELSE  
      ENAME := GET_LAST_EXECUTION(TASK_ID_NUM);
      MERGE INTO WRI$_ADV_EXEC_PARAMETERS P
      USING (SELECT TASK_ID_NUM TASK_ID, ENAME EXEC_NAME, L_NAME NAME, 
                    L_DATA VALUE
             FROM   DUAL) I
      ON    (P.TASK_ID = I.TASK_ID AND P.EXEC_NAME = I.EXEC_NAME AND 
             P.NAME = I.NAME)
      WHEN MATCHED THEN
        UPDATE SET P.VALUE = I.VALUE
      WHEN NOT MATCHED THEN
        INSERT(TASK_ID, EXEC_NAME, NAME, VALUE)
        VALUES(I.TASK_ID, I.EXEC_NAME, I.NAME, I.VALUE);
    END IF;     
    UPDATE_TASK(TASK_ID_NUM);
    COMMIT;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
    RETURN;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
      RAISE;
  END SET_TASK_PARAMETER;
PROCEDURE SET_TASK_PARAMETER(
  TASK_NAME     IN VARCHAR2,
  PARAMETER     IN VARCHAR2,
  DATA          IN NUMBER,
  PROP          IN BINARY_INTEGER := 0,
  SCOPE         IN BINARY_INTEGER := FUTURE_EXECUTIONS,
  TASK_OWNER_ID IN BINARY_INTEGER := -1)
  IS
  BEGIN
    SET_TASK_PARAMETER(TASK_NAME, 
                       PARAMETER, 
                       NVL(TO_CHAR(DATA), 'UNUSED'), 
                       PROP,
                       SCOPE,
                       TASK_OWNER_ID);
  END SET_TASK_PARAMETER;
PROCEDURE SET_DEFAULT_TASK_PARAMETER (ADVISOR_NAME   IN VARCHAR2,
                                      PARAMETER      IN VARCHAR2,
                                      VALUE          IN VARCHAR2)
  IS
    CNT NUMBER;
    L_DATA SYS.WRI$_ADV_DEF_PARAMETERS.VALUE%TYPE;
    L_NAME SYS.WRI$_ADV_DEF_PARAMETERS.NAME%TYPE;
    TP SYS.WRI$_ADV_ABSTRACT_T;
  BEGIN
    TP := VALIDATE_ADVISOR(ADVISOR_NAME);
    IF PARAMETER IS NOT NULL AND LENGTH(PARAMETER) > 30 THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'PARAMETER');    
    ELSE
      L_NAME := NVL(UPPER(PARAMETER), 'NULL');
    END IF;
    SELECT COUNT(*) INTO CNT
      FROM SYS.WRI$_ADV_DEF_PARAMETERS
      WHERE ADVISOR_ID = TP.ADVISOR_ID
        AND NAME = L_NAME;
    IF CNT = 0 THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(PARAM_NOT_FOUND, 
                                        L_NAME, 
                                        ADVISOR_NAME);
    END IF;
    IF (LENGTH(VALUE) > 4000) THEN 
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'VALUE');    
    ELSE 
      L_DATA := VALUE;
    END IF; 
    IF L_DATA IS NULL OR LENGTH(L_DATA) = 0 THEN
      L_DATA := 'UNUSED';
    ELSIF L_DATA = TO_CHAR(DBMS_ADVISOR.ADVISOR_ALL) OR L_DATA = '%' THEN
      L_DATA := 'ALL';
    ELSIF L_DATA = TO_CHAR(DBMS_ADVISOR.ADVISOR_CURRENT) THEN
      L_DATA := 'CURRENT';
    ELSIF L_DATA = TO_CHAR(DBMS_ADVISOR.ADVISOR_UNLIMITED) THEN
      L_DATA := 'UNLIMITED';
    END IF;
    VALIDATE_FMWK_PARAMS(-1, TP.ADVISOR_ID, L_NAME, L_DATA);
    TP.SUB_PARAM_VALIDATE(-1, L_NAME, L_DATA);
    UPDATE SYS.WRI$_ADV_DEF_PARAMETERS
      SET VALUE = L_DATA
      WHERE NAME = L_NAME
        AND ADVISOR_ID = TP.ADVISOR_ID;
    COMMIT;
    RETURN;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
      RAISE;
  END SET_DEFAULT_TASK_PARAMETER;
PROCEDURE SET_DEFAULT_TASK_PARAMETER (ADVISOR_NAME   IN VARCHAR2,
                                      PARAMETER      IN VARCHAR2,
                                      VALUE          IN NUMBER)
  IS
  BEGIN
    SET_DEFAULT_TASK_PARAMETER(ADVISOR_NAME, 
                               PARAMETER, 
                               NVL(TO_CHAR(VALUE), 'UNUSED'));
  END SET_DEFAULT_TASK_PARAMETER;
PROCEDURE CREATE_OBJECT(TASK_NAME     IN VARCHAR2 ,
                        OBJECT_TYPE   IN VARCHAR2 ,
                        ATTR1         IN VARCHAR2 := NULL,
                        ATTR2         IN VARCHAR2 := NULL,
                        ATTR3         IN VARCHAR2 := NULL,
                        ATTR4         IN CLOB     := NULL,
                        ATTR5         IN VARCHAR2 := NULL,
                        OBJECT_ID    OUT NUMBER,
                        ATTR6         IN RAW      := NULL,
                        ATTR7         IN NUMBER   := NULL,
                        ATTR8         IN NUMBER   := NULL,
                        ATTR9         IN NUMBER   := NULL,
                        ATTR10        IN NUMBER   := NULL)
IS
   TASK_ID_NUM BINARY_INTEGER := 0;
   OBJ_ID      BINARY_INTEGER := 0;
   TYPE_ID     BINARY_INTEGER := 0;
   CURSOR OBJ_TYPEID_CUR (TYPE_STR VARCHAR2) IS
     SELECT OBJECT_TYPE_ID
       FROM DBA_ADVISOR_OBJECT_TYPES
       WHERE OBJECT_TYPE = TYPE_STR;
BEGIN
    TASK_ID_NUM := VALIDATE_TASK(TASK_NAME);
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_X);
    CHECK_MODIFY(TASK_NAME, TASK_ID_NUM);
    CHECK_INITIAL(TASK_NAME, TASK_ID_NUM);
    OPEN OBJ_TYPEID_CUR(OBJECT_TYPE);
    FETCH OBJ_TYPEID_CUR INTO TYPE_ID;
    IF OBJ_TYPEID_CUR%NOTFOUND THEN
       CLOSE OBJ_TYPEID_CUR;
       DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INVALID_OBJ_TYPE, 
                                         ADJUST_STRING(OBJECT_TYPE, 64));
    END IF;
    CLOSE OBJ_TYPEID_CUR;
    SELECT NVL(MAX(ID), 0) INTO OBJ_ID
      FROM SYS.WRI$_ADV_OBJECTS A
      WHERE A.TASK_ID = TASK_ID_NUM;
    OBJ_ID := OBJ_ID + 1;
    INSERT INTO SYS.WRI$_ADV_OBJECTS
      (ID, TYPE, TASK_ID, ATTR1, ATTR2, ATTR3, ATTR4, ATTR5, ATTR6, ATTR7, 
       ATTR8, ATTR9, ATTR10)
    VALUES
      (OBJ_ID, TYPE_ID, TASK_ID_NUM, ATTR1, ATTR2, ATTR3, ATTR4, ATTR5, ATTR6,
       ATTR7, ATTR8, ATTR9, ATTR10);
    UPDATE_TASK(TASK_ID_NUM);
    COMMIT;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
    OBJECT_ID := OBJ_ID;
    RETURN;
EXCEPTION
   WHEN OTHERS THEN
     ROLLBACK;
     HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
     RAISE;
END CREATE_OBJECT;
PROCEDURE CREATE_OBJECT(TASK_NAME     IN VARCHAR2 ,
                        OBJECT_TYPE   IN VARCHAR2 ,
                        ATTR1         IN VARCHAR2 := NULL,
                        ATTR2         IN VARCHAR2 := NULL,
                        ATTR3         IN VARCHAR2 := NULL,
                        ATTR4         IN CLOB     := NULL,
                        OBJECT_ID    OUT NUMBER)
IS
BEGIN
  CREATE_OBJECT(TASK_NAME, 
                OBJECT_TYPE, 
                ATTR1, 
                ATTR2, 
                ATTR3, 
                ATTR4, 
                NULL, 
                OBJECT_ID,
                NULL,
                ATTR7 => NULL,
                ATTR8 => NULL,
                ATTR9 => NULL);
END CREATE_OBJECT;
PROCEDURE UPDATE_OBJECT(TASK_NAME     IN VARCHAR2 ,
                        OBJECT_ID     IN NUMBER ,
                        A1            IN VARCHAR2 := NULL,
                        A2            IN VARCHAR2 := NULL,
                        A3            IN VARCHAR2 := NULL,
                        A4            IN CLOB := NULL,
                        A5            IN VARCHAR2 := NULL)
IS
   TASK_ID_NUM BINARY_INTEGER := 0;
BEGIN
    TASK_ID_NUM := VALIDATE_TASK(TASK_NAME);
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_X);
    CHECK_MODIFY(TASK_NAME, TASK_ID_NUM);
    CHECK_INITIAL(TASK_NAME, TASK_ID_NUM);
    VALIDATE_OBJECT(TASK_NAME, TASK_ID_NUM, OBJECT_ID);
    UPDATE WRI$_ADV_OBJECTS
      SET ATTR1 = NVL(A1, ATTR1),
          ATTR2 = NVL(A2, ATTR2),
          ATTR3 = NVL(A3, ATTR3),
          ATTR4 = NVL(A4, ATTR4),
          ATTR5 = NVL(A5, ATTR5)
      WHERE TASK_ID = TASK_ID_NUM AND
            ID = OBJECT_ID;
    UPDATE_TASK(TASK_ID_NUM);
    COMMIT;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
    RETURN;
EXCEPTION
   WHEN OTHERS THEN
     ROLLBACK;
     HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
     RAISE;
END UPDATE_OBJECT;
PROCEDURE UPDATE_REC_ATTRIBUTES (TASK_NAME            IN VARCHAR2,
                                 REC_ID               IN NUMBER,
                                 ACTION_ID            IN NUMBER,
                                 ATTRIBUTE_NAME       IN VARCHAR2,
                                 VALUE                IN VARCHAR2)
  IS
    TASK_ID_NUM BINARY_INTEGER := 0;
    CNT NUMBER;
    TP SYS.WRI$_ADV_ABSTRACT_T;
    RECOM_ID NUMBER := REC_ID;
  BEGIN
    TASK_ID_NUM := VALIDATE_TASK (TASK_NAME);
    TP := FETCH_ADVISOR(TASK_ID_NUM);
    CHECK_EXECUTION_STATUS(TASK_NAME, TASK_ID_NUM);
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_X);
    CHECK_MODIFY(TASK_NAME, TASK_ID_NUM);
    SELECT COUNT(*) INTO CNT
      FROM SYS.WRI$_ADV_REC_ACTIONS A
      WHERE A.ACT_ID = ACTION_ID AND A.REC_ID = RECOM_ID AND
            A.TASK_ID = TASK_ID_NUM;
    IF CNT = 0 THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INVALID_REC,
                                        TO_CHAR(REC_ID),
                                        TO_CHAR(ACTION_ID),
                                        TASK_NAME);
    END IF;
    IF ATTRIBUTE_NAME IS NULL THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'ATTRIBUTE_NAME');
    END IF;
    TP.SUB_UPDATE_REC_ATTR(TASK_ID_NUM, 
                           REC_ID, 
                           ACTION_ID, 
                           UPPER(ATTRIBUTE_NAME), 
                           NVL(VALUE, TO_CHAR(NULL)));
    UPDATE_TASK(TASK_ID_NUM);
    COMMIT;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
    RETURN;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
      HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
      RAISE;
  END UPDATE_REC_ATTRIBUTES;
PROCEDURE UPDATE_TASK_ATTRIBUTES (TASK_NAME       IN VARCHAR2,
                                  NEW_NAME        IN VARCHAR2,
                                  DESCRIPTION     IN VARCHAR2,
                                  READ_ONLY       IN VARCHAR2,
                                  IS_TEMPLATE     IN VARCHAR2,
                                  HOW_CREATED     IN VARCHAR2,
                                  PROP            IN BINARY_INTEGER)
  IS
    TASK_ID_NUM BINARY_INTEGER := 0;
    TMP VARCHAR2(32767);
    L_PROP BINARY_INTEGER;
    NEW_PROP BINARY_INTEGER;
    L_READ VARCHAR2(50);
    L_TEMP VARCHAR2(50);
    L_NAME VARCHAR2(30);
    BIT_READONLY BINARY_INTEGER;
    BIT_TEMPLATE BINARY_INTEGER;
  BEGIN
    BIT_READONLY := TASK_PROP_READONLY;
    BIT_TEMPLATE := TASK_PROP_TEMPLATE;
    TASK_ID_NUM := VALIDATE_TASK(TASK_NAME, PROP);
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_X);
    SELECT PROPERTY INTO L_PROP FROM SYS.WRI$_ADV_TASKS
      WHERE ID = TASK_ID_NUM;
    NEW_PROP := L_PROP;
    IF READ_ONLY IS NOT NULL AND
       READ_ONLY <> TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) THEN
      IF BITAND(NEW_PROP,BIT_READONLY) = BIT_READONLY THEN
        NEW_PROP := NEW_PROP - BIT_READONLY;
      END IF;
      L_READ := UPPER(READ_ONLY);
      IF L_READ = 'TRUE' THEN
        NEW_PROP := NEW_PROP + BIT_READONLY;
      ELSIF L_READ <> 'FALSE' THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'READ_ONLY');
      END IF;
    END IF;
    IF IS_TEMPLATE IS NOT NULL AND
       IS_TEMPLATE <> TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) THEN
      IF BITAND(NEW_PROP,BIT_TEMPLATE) = BIT_TEMPLATE THEN
        NEW_PROP := NEW_PROP - BIT_TEMPLATE;
      END IF;
      L_TEMP := UPPER(IS_TEMPLATE);
      IF L_TEMP = 'TRUE' THEN
        NEW_PROP := NEW_PROP + BIT_TEMPLATE;
      ELSIF L_TEMP <> 'FALSE' THEN
         DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'IS_TEMPLATE');
      END IF;
    END IF;
    IF L_PROP <> NEW_PROP THEN
      UPDATE SYS.WRI$_ADV_TASKS A
        SET A.PROPERTY = NEW_PROP
        WHERE A.ID = TASK_ID_NUM;
    END IF;
    IF NOT IS_EMPTY(NEW_NAME, TMP) THEN
      L_NAME := VALIDATE_NEW_TASK(NEW_NAME, NULL, PROP);
      CHECK_MODIFY(TASK_NAME, TASK_ID_NUM);
      CHECK_INITIAL(TASK_NAME, TASK_ID_NUM);
      UPDATE SYS.WRI$_ADV_TASKS A
          SET A.NAME = L_NAME
        WHERE A.ID = TASK_ID_NUM;
    END IF;
    IF DESCRIPTION IS NOT NULL AND
       DESCRIPTION <> TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) THEN
      VALIDATE_ITEM_LENGTH(DESCRIPTION, DESC_NAME, 256);
      TMP := DESCRIPTION;
      CHECK_MODIFY(TASK_NAME, TASK_ID_NUM);
      CHECK_INITIAL(TASK_NAME, TASK_ID_NUM);
      UPDATE SYS.WRI$_ADV_TASKS A
        SET A.DESCRIPTION = TMP
        WHERE A.ID = TASK_ID_NUM;
    END IF;
    IF HOW_CREATED IS NOT NULL AND
       HOW_CREATED <> TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) THEN
      TMP := SUBSTR(HOW_CREATED,1,30);
      CHECK_MODIFY(TASK_NAME, TASK_ID_NUM);
      CHECK_INITIAL(TASK_NAME, TASK_ID_NUM);
      UPDATE SYS.WRI$_ADV_TASKS A
        SET A.HOW_CREATED = TMP
        WHERE A.ID = TASK_ID_NUM;
    END IF;
    UPDATE_TASK(TASK_ID_NUM);
    COMMIT;
    HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
    RETURN;
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        HANDLE_LOCK(TASK_ID_NUM, TASK_LOCK_R);
      RAISE;
  END UPDATE_TASK_ATTRIBUTES;
PROCEDURE CREATE_TASK (ADVISOR_NAME          IN VARCHAR2,
                       TASK_NAME             IN VARCHAR2,
                       TASK_DESC             IN VARCHAR2,
                       TEMPLATE              IN VARCHAR2,
                       IS_TEMPLATE           IN VARCHAR2,
                       PROP                  IN BINARY_INTEGER,
                       HOW_CREATED           IN VARCHAR2)
  IS
    L_TASK_ID   NUMBER;
    L_TASK_NAME VARCHAR2(32767) := TASK_NAME; 
  BEGIN
    CREATE_TASK(ADVISOR_NAME, L_TASK_ID, L_TASK_NAME, TASK_DESC,
                TEMPLATE, IS_TEMPLATE, PROP, HOW_CREATED);
  END CREATE_TASK;
PROCEDURE CREATE_TASK(ADVISOR_NAME          IN VARCHAR2,
                      TASK_ID               OUT NUMBER,
                      TASK_NAME             IN OUT VARCHAR2,
                      TASK_DESC             IN VARCHAR2,
                      TEMPLATE              IN VARCHAR2,
                      IS_TEMPLATE           IN VARCHAR2,
                      PROP                  IN BINARY_INTEGER,
                      HOW_CREATED           IN VARCHAR2,
                      PARENT_ID             IN NUMBER := NULL)  
  IS
    ID BINARY_INTEGER;
    FROM_ID BINARY_INTEGER;
    FROM_ID_ADVISOR BINARY_INTEGER;
    TP WRI$_ADV_ABSTRACT_T;
    FROM_TP WRI$_ADV_ABSTRACT_T;
    L_PROP BINARY_INTEGER;
    L_TASK_NAME        VARCHAR2(32767) := NULL;
    L_TASK_OWNER       NUMBER;
    L_TASK_OWNER_NAME  VARCHAR2(32767) := NULL;
  BEGIN
    IF PROP IS NULL OR PROP = 0 THEN
      L_PROP := TASK_PROP_TASK;
    ELSE
      L_PROP := PROP;
    END IF;
    IF IS_TEMPLATE IS NOT NULL THEN
      IF UPPER(IS_TEMPLATE) = 'TRUE' THEN
        L_PROP := L_PROP + TASK_PROP_TEMPLATE;
      ELSIF UPPER(IS_TEMPLATE) <> 'FALSE' THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'IS_TEMPLATE');
      END IF;
    END IF;
    TP := VALIDATE_ADVISOR(ADVISOR_NAME);
    IF (PARENT_ID IS NOT NULL AND PARENT_ID <> 0) THEN
      VALIDATE_TASK_ID(PARENT_ID, L_TASK_NAME, L_TASK_OWNER_NAME, 
                       L_TASK_OWNER);
    END IF;
    TP.SUB_USER_SETUP(TP.ADVISOR_ID);
    IF (TEMPLATE IS NOT NULL AND 
        TEMPLATE != TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) AND 
        LENGTH(TEMPLATE) != 0) 
    THEN
      FROM_ID := VALIDATE_TASK(TEMPLATE, L_PROP);
      FROM_TP := FETCH_ADVISOR(FROM_ID);
      IF FROM_TP.ADVISOR_ID != TP.ADVISOR_ID THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INCOMPAT_ADV, TEMPLATE);
      END IF;
    ELSE
      FROM_ID := 0;
    END IF;
    IF (FROM_ID > 0) THEN
       HANDLE_LOCK(FROM_ID, TASK_LOCK_S);
    END IF;
    TASK_ID := COMMON_CREATE_TASK(TASK_NAME,
                                  TASK_DESC,
                                  TP,
                                  NVL(PARENT_ID, 0), 
                                  0,
                                  FROM_ID,
                                  HOW_CREATED,
                                  L_PROP);
    IF (FROM_ID > 0) THEN
       HANDLE_LOCK(FROM_ID, TASK_LOCK_R);
    END IF;
    COMMIT;
    RETURN; 
  EXCEPTION
    WHEN OTHERS THEN
      ROLLBACK;
      IF (FROM_ID > 0) THEN
         HANDLE_LOCK(FROM_ID, TASK_LOCK_R);
      END IF;
    RAISE;
  END CREATE_TASK;
PROCEDURE CREATE_TASK (PARENT_TASK_NAME      IN VARCHAR2,
                       REC_ID                IN NUMBER,
                       TASK_ID               OUT NUMBER,
                       TASK_NAME             IN OUT VARCHAR2,
                       TASK_DESC             IN VARCHAR2,
                       TEMPLATE              IN VARCHAR2,
                       PROP                  IN BINARY_INTEGER)
  IS
  BEGIN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOT_SUPPORTED);
    RETURN;
  END CREATE_TASK;
PROCEDURE PARSE_NAME(NAME VARCHAR2, PROP BINARY_INTEGER)
  IS
    TMP_NAME VARCHAR2(32767);    
  BEGIN
    IF LENGTH(NAME)  > 30 THEN
      RAISE_TASK_NAME_ERROR(NAME, PROP);
    END IF;
    IF IS_EMPTY(NAME, TMP_NAME) THEN
      RAISE_TASK_NAME_ERROR(TMP_NAME, PROP);
    END IF;
    IF IS_KEYWORD(NAME, TMP_NAME) THEN
      RAISE_TASK_NAME_ERROR(NAME, PROP);
    END IF;
    IF IS_WILDCARD(NAME, TMP_NAME) THEN
      RAISE_TASK_NAME_ERROR(TMP_NAME, PROP);
    END IF;
  END PARSE_NAME;
FUNCTION GET_DB_VERSION
  RETURN BINARY_INTEGER
  IS
  EXTERNAL
  NAME "keauGetDbVersionPLSQL"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   RETURN UB4
  );
FUNCTION EDIT (INBUF         VARCHAR2,
               FLAGS         BINARY_INTEGER)
  RETURN VARCHAR2
  IS
  EXTERNAL
  NAME "keasEditPLSQL"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   INBUF OCISTRING,
   INBUF INDICATOR SB2,
   FLAGS UB4,
   RETURN INDICATOR SB2,
   RETURN LENGTH UB4,
   RETURN
  );
PROCEDURE DELETE_MESSAGE (TASK_NUM    IN BINARY_INTEGER,
                          MSG_ID      IN BINARY_INTEGER)
  IS
  BEGIN
    DELETE FROM SYS.WRI$_ADV_MESSAGE_GROUPS
     WHERE TASK_ID = TASK_NUM
        AND ID = MSG_ID;
  END DELETE_MESSAGE;
FUNCTION VALIDATE_COMMAND(COMMAND   VARCHAR2)
  RETURN BINARY_INTEGER
  IS
    CODE BINARY_INTEGER;
  BEGIN
    SELECT INDX INTO CODE FROM X$KEACMDN
      WHERE COMMAND_NAME = COMMAND;
    RETURN CODE;
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INVALID_COMMAND, 
                                          ADJUST_STRING(COMMAND, 64));
  END VALIDATE_COMMAND;
PROCEDURE RECORD_JOURNAL (TASK_ID   BINARY_INTEGER,
                          JOU_TYPE  BINARY_INTEGER,
                          CODE      VARCHAR2,
                          ARG1      VARCHAR2 := NULL,
                          ARG2      VARCHAR2 := NULL,
                          ARG3      VARCHAR2 := NULL,
                          ARG4      VARCHAR2 := NULL,
                          ARG5      VARCHAR2 := NULL)
  IS
  EXTERNAL
  NAME "keauRecordJournalPLSQL"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   TASK_ID UB4,
   JOU_TYPE UB4,
   CODE OCISTRING,
   CODE INDICATOR SB2,
   ARG1 OCISTRING,
   ARG1 INDICATOR SB2,
   ARG2 OCISTRING,
   ARG2 INDICATOR SB2,
   ARG3 OCISTRING,
   ARG3 INDICATOR SB2,
   ARG4 OCISTRING,
   ARG4 INDICATOR SB2,
   ARG5 OCISTRING,
   ARG5 INDICATOR SB2
  );
FUNCTION FORMAT_MESSAGE (INC_HEADER   BINARY_INTEGER,
                         CODE         VARCHAR2,
                         ARG1         VARCHAR2 := NULL,
                         ARG2         VARCHAR2 := NULL,
                         ARG3         VARCHAR2 := NULL,
                         ARG4         VARCHAR2 := NULL,
                         ARG5         VARCHAR2 := NULL)
  RETURN VARCHAR2
  IS
  EXTERNAL
  NAME "keauFormatMsgPLSQL"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   INC_HEADER UB1,
   CODE OCISTRING,
   CODE INDICATOR SB2,
   ARG1 OCISTRING,
   ARG1 INDICATOR SB2,
   ARG2 OCISTRING,
   ARG2 INDICATOR SB2,
   ARG3 OCISTRING,
   ARG3 INDICATOR SB2,
   ARG4 OCISTRING,
   ARG4 INDICATOR SB2,
   ARG5 OCISTRING,
   ARG5 INDICATOR SB2,
   RETURN INDICATOR SB2,
   RETURN LENGTH UB4,
   RETURN
  );
FUNCTION FORMAT_MESSAGE_GROUP(GROUP_ID IN BINARY_INTEGER,
                              MSG_TYPE IN BINARY_INTEGER := 0)
  RETURN VARCHAR2
  IS
  EXTERNAL
  NAME "keauFormatMsgGroupPLSQL"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   GROUP_ID UB4,
   MSG_TYPE UB4,
   RETURN INDICATOR SB2,
   RETURN LENGTH UB4,
   RETURN
  );
PROCEDURE RECORD_ERRORMSG(TASK_NUM  IN BINARY_INTEGER,
                          EXEC_NAME IN VARCHAR2,
                          ERR_NUM   IN BINARY_INTEGER)
  IS
  EXTERNAL
  NAME "keauRecordErrorMsg"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   TASK_NUM UB4,
   EXEC_NAME STRING, EXEC_NAME INDICATOR SB2,
   ERR_NUM  UB4
  );
PROCEDURE HANDLE_LOCK (TASK_ID     BINARY_INTEGER,
                       LOCK_OPTION BINARY_INTEGER,
                       TIMEOUT     BINARY_INTEGER)
  IS
  EXTERNAL
  NAME "keauhtlPLSQL"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   TASK_ID UB4,
   LOCK_OPTION UB4,
   TIMEOUT UB4
  );
PROCEDURE SIGNAL_INTERRUPT (TASK_ID     BINARY_INTEGER,
                            INTR_OPTION BINARY_INTEGER)
  IS
  EXTERNAL
  NAME "keauInterruptTaskPLSQL"
  LIBRARY DBMS_KEA_LIB
  WITH CONTEXT
  LANGUAGE C
  PARAMETERS
  (CONTEXT,
   TASK_ID UB4,
   INTR_OPTION UB4
  );
PROCEDURE UPDATE_TASK(
  TASK_ID        IN BINARY_INTEGER,
  NEW_STATUS     IN BINARY_INTEGER := NULL,
  NEW_CLEANUP    IN BINARY_INTEGER := NULL,
  DB_VERSION     IN BINARY_INTEGER := NULL)
  IS
  BEGIN
    UPDATE SYS.WRI$_ADV_TASKS
       SET MTIME = SYSDATE,
           STATUS = NVL(NEW_STATUS, STATUS),
           CLEANUP = NVL(NEW_CLEANUP, CLEANUP),
           VERSION = NVL(DB_VERSION, VERSION)
    WHERE ID = TASK_ID;
  END UPDATE_TASK;
PROCEDURE UPDATE_TASK(
  TASK_ID        IN BINARY_INTEGER,
  LAST_EXECUTION IN VARCHAR2,
  NEW_STATUS     IN BINARY_INTEGER := NULL,
  NEW_CLEANUP    IN BINARY_INTEGER := NULL,
  DB_VERSION     IN BINARY_INTEGER := NULL)
  IS
  BEGIN
    UPDATE SYS.WRI$_ADV_TASKS
       SET MTIME = SYSDATE,
           LAST_EXEC_NAME = LAST_EXECUTION,
           STATUS = NVL(NEW_STATUS, STATUS),
           CLEANUP = NVL(NEW_CLEANUP, CLEANUP),
           VERSION = NVL(DB_VERSION, VERSION)
    WHERE ID = TASK_ID;
  END UPDATE_TASK;
FUNCTION IS_WILDCARD (NAME          VARCHAR2,
                      DISPLAY_NAME  OUT VARCHAR2)
  RETURN BOOLEAN
  IS
  BEGIN
    IF NAME IS NULL OR NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) THEN
      RETURN (FALSE);
    END IF;
    IF LENGTH(NAME) = 0 THEN
      RETURN (FALSE);
    END IF;
    IF INSTR(NAME,'%') > 0 THEN
      DISPLAY_NAME := NAME;
      RETURN (TRUE);
    END IF;
    IF NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_ALL) THEN
      DISPLAY_NAME := '%';
      RETURN (TRUE);
    END IF;
    RETURN (FALSE);
  END IS_WILDCARD;
PROCEDURE VALIDATE_ITEM_LENGTH (VALUE     IN VARCHAR2,
                                NAME_ID   IN VARCHAR2,
                                MAX_LEN   IN BINARY_INTEGER)
  IS
    NAME VARCHAR2(250);
  BEGIN
    IF VALUE IS NULL THEN
      RETURN;
    END IF;
    IF LENGTHB(VALUE) > MAX_LEN THEN
      NAME := FORMAT_MESSAGE(0,NAME_ID);
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ITEM_TOO_LONG, NAME, MAX_LEN);
    END IF;
    RETURN;
  END VALIDATE_ITEM_LENGTH;
FUNCTION IS_KEYWORD (NAME   VARCHAR2, DISPLAY_NAME OUT VARCHAR2)
  RETURN BOOLEAN
  IS
    VALUE BOOLEAN;
    TMP VARCHAR2(30);
  BEGIN
    IF NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_ALL) THEN
      VALUE := TRUE;
      DISPLAY_NAME := 'DBMS_ADVISOR.ADVISOR_ALL';
    ELSIF NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) THEN
      VALUE := TRUE;
      DISPLAY_NAME := 'DBMS_ADVISOR.ADVISOR_UNUSED';
    ELSIF NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_CURRENT) THEN
      VALUE := TRUE;
      DISPLAY_NAME := 'DBMS_ADVISOR.ADVISOR_CURRENT';
    ELSIF NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_DEFAULT) THEN
      VALUE := TRUE;
      DISPLAY_NAME := 'DBMS_ADVISOR.ADVISOR_DEFAULT';
    ELSIF NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_UNLIMITED) THEN
      VALUE := TRUE;
      DISPLAY_NAME := 'DBMS_ADVISOR.ADVISOR_UNLIMITED';
    ELSE
      VALUE := FALSE;
    END IF;
    RETURN (VALUE);
  END IS_KEYWORD;
PROCEDURE CHECK_INITIAL(TASK_NAME IN VARCHAR2, TASK_ID IN BINARY_INTEGER)
  IS
    L_STATUS BINARY_INTEGER;
  BEGIN
    SELECT STATUS INTO L_STATUS
      FROM WRI$_ADV_TASKS
      WHERE ID = TASK_ID;
    IF L_STATUS != TASK_STATE_INITIAL THEN
       DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(TASK_NOT_INITIAL, TASK_NAME);
    END IF;
  END CHECK_INITIAL;
PROCEDURE CHECK_MODIFY(TASK_NAME IN VARCHAR2, TASK_ID IN BINARY_INTEGER)
  IS
    PROP BINARY_INTEGER;
  BEGIN
    SELECT PROPERTY INTO PROP FROM SYS.WRI$_ADV_TASKS
     WHERE ID = TASK_ID;
    IF BITAND(PROP,TASK_PROP_READONLY) = TASK_PROP_READONLY THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(READ_ONLY, TASK_NAME);
    END IF;
  END CHECK_MODIFY;
PROCEDURE CHECK_TEMPLATE(TASK_NAME VARCHAR2, TASK_ID IN BINARY_INTEGER)
  IS
    PROP BINARY_INTEGER;
  BEGIN
    SELECT PROPERTY INTO PROP FROM SYS.WRI$_ADV_TASKS
     WHERE ID = TASK_ID;
    IF BITAND(PROP,TASK_PROP_TEMPLATE) = TASK_PROP_TEMPLATE THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(BAD_TEMP_OP, TASK_NAME);
    END IF;
  END CHECK_TEMPLATE;
PROCEDURE CHECK_EXECUTION_STATUS(TASK_NAME   IN VARCHAR2,
                                 TASK_ID_NUM IN BINARY_INTEGER,
                                 EXEC_NAME   IN VARCHAR2 := NULL,
                                 ALLOW_ERROR IN BOOLEAN := FALSE)
  IS
   L_STATUS BINARY_INTEGER;
  BEGIN
    IF (EXEC_NAME IS NULL) THEN
      SELECT STATUS# INTO L_STATUS FROM SYS.DBA_ADVISOR_TASKS
      WHERE TASK_ID = TASK_ID_NUM;
    ELSE
      SELECT STATUS# INTO L_STATUS FROM SYS.DBA_ADVISOR_EXECUTIONS
      WHERE  TASK_ID = TASK_ID_NUM AND EXECUTION_NAME = EXEC_NAME;
    END IF;
    IF (L_STATUS <> TASK_STATE_COMPLETED AND
        L_STATUS <> TASK_STATE_INTERRUPTED AND
        (NOT ALLOW_ERROR OR L_STATUS <> TASK_STATE_ERROR) ) THEN
      IF (EXEC_NAME IS NULL) THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOEXEC_RESULTS, TASK_NAME);
      ELSE
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOEXEC_RESULTS_FOREXEC, 
                                          TASK_NAME, EXEC_NAME);
      END IF;
    END IF;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXEC_NOT_FOUND, EXEC_NAME);
    WHEN OTHERS THEN
      RAISE;
  END CHECK_EXECUTION_STATUS;
FUNCTION IS_EMPTY (NAME   IN VARCHAR2, DISPLAY_NAME OUT VARCHAR2)
  RETURN BOOLEAN
  IS
BEGIN
    IF NAME IS NULL THEN
       DISPLAY_NAME := FORMAT_MESSAGE(0, TASK_NULL);
      RETURN (TRUE);
    END IF;
    IF NAME = TO_CHAR(DBMS_ADVISOR.ADVISOR_UNUSED) THEN
      DISPLAY_NAME := 'DBMS_ADVISOR.UNUSED';
      RETURN (TRUE);
    END IF;
    IF LENGTH(NAME) = 0 THEN
      DISPLAY_NAME := FORMAT_MESSAGE(0, TASK_EMPTY);
      RETURN (TRUE);
    END IF;
    RETURN (FALSE);
  END IS_EMPTY;
FUNCTION FETCH_ADVISOR (TASK_ID   BINARY_INTEGER)
  RETURN SYS.WRI$_ADV_ABSTRACT_T
  IS
    TP SYS.WRI$_ADV_ABSTRACT_T;
  BEGIN
    SELECT B.TYPE INTO TP
      FROM SYS.WRI$_ADV_TASKS A, SYS.WRI$_ADV_DEFINITIONS B
      WHERE A.ADVISOR_ID = B.ID
        AND A.ID = TASK_ID;
    RETURN (TP);
  END FETCH_ADVISOR;
FUNCTION VALIDATE_ADVISOR (ADVISOR_NAME   VARCHAR2)
  RETURN SYS.WRI$_ADV_ABSTRACT_T
  IS
    ID BINARY_INTEGER;
    TP SYS.WRI$_ADV_ABSTRACT_T;
  BEGIN
    SELECT A.ID,A.TYPE INTO ID,TP FROM SYS.WRI$_ADV_DEFINITIONS A
      WHERE A.NAME = ADVISOR_NAME;
    TP.ADVISOR_ID := ID;
    RETURN (TP);
  EXCEPTION
    WHEN OTHERS THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ADVISOR_NOT_FOUND, 
                                        ADJUST_STRING(ADVISOR_NAME, 30));
  END VALIDATE_ADVISOR;
FUNCTION CHECK_RESERVED_TASK_NAME (TASK_NAME IN VARCHAR2)
  RETURN BOOLEAN
  IS
    IDX NUMBER;
  BEGIN
    FOR IDX IN TASK_RESERVED_NAMES.FIRST .. TASK_RESERVED_NAMES.LAST LOOP
      IF (TASK_RESERVED_NAMES(IDX) = TASK_NAME) THEN
        RETURN TRUE;
      END IF;
    END LOOP;
    RETURN FALSE;
  END CHECK_RESERVED_TASK_NAME;
FUNCTION VALIDATE_NEW_TASK(TASK_NAME IN VARCHAR2,
                           TASK_NUM  IN NUMBER, 
                           PROP      IN BINARY_INTEGER)
  RETURN VARCHAR2
  IS
    CNT BINARY_INTEGER;
    L_PROP BINARY_INTEGER;
    L_NAME VARCHAR2(32767) := TASK_NAME;
    L_USER_ID BINARY_INTEGER;
    BUF VARCHAR2(32767);
  BEGIN
    IF PROP IS NULL OR PROP = 0 THEN
      L_PROP := TASK_PROP_TASK;
    ELSE
      L_PROP := PROP;
    END IF;
    L_USER_ID := SYS_CONTEXT('USERENV', 'SESSION_USERID');
    IF NOT IS_EMPTY(TASK_NAME, BUF) THEN
      PARSE_NAME(TASK_NAME, L_PROP);
      IF (BITAND(L_PROP, TASK_PROP_RESERVEDNAME) = 0 AND 
          CHECK_RESERVED_TASK_NAME(L_NAME)) THEN
        RAISE_TASK_NAME_ERROR(L_NAME, L_PROP);
      END IF;
      SELECT COUNT(*) INTO CNT FROM SYS.WRI$_ADV_TASKS A
       WHERE A.NAME = L_NAME
         AND A.OWNER# = L_USER_ID
         AND BITAND(A.PROPERTY, L_PROP) = L_PROP;
      IF CNT > 0 THEN
        IF PROP = TASK_PROP_WORKLOAD THEN
          BUF := FORMAT_MESSAGE(1, WRK_EXISTS, L_NAME);
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ADVISOR_ERROR, BUF);
        ELSE
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(TASK_ALREADY_EXISTS, L_NAME);
        END IF;
      END IF;
    ELSE 
      IF PROP = TASK_PROP_WORKLOAD THEN
        BUF := FORMAT_MESSAGE(0, WORK_KEYWORD);
      ELSE
        BUF := FORMAT_MESSAGE(0, TASK_KEYWORD);
      END IF;
      IF NOT (GENERATE_UNIQUE_NAME(TARGET_TYPE => 'TASK', 
                                   TARGET_PREFIX => UPPER(SUBSTR(BUF, 1, 24)), 
                                   TARGET_ID => TASK_NUM, 
                                   TARGET_OWNER => L_USER_ID, 
                                   TARGET_PROP => PROP,
                                   NEW_NAME => L_NAME)) 
      THEN 
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(TASK_ALREADY_EXISTS, L_NAME);
      END IF;
    END IF;  
    RETURN (L_NAME);
  END VALIDATE_NEW_TASK;
FUNCTION VALIDATE_TASK(TASK_NAME     VARCHAR2,
                       PROP          BINARY_INTEGER := 0,
                       USER_ID       BINARY_INTEGER := -1,
                       ADVISOR_NAME  VARCHAR2 := NULL)
  RETURN NUMBER
  IS
    L_ID       BINARY_INTEGER;
    L_PROP     BINARY_INTEGER;
    BUF        VARCHAR2(500);
    L_USER_ID  BINARY_INTEGER;
    L_ADV_NAME VARCHAR2(30);
  BEGIN
    IF PROP IS NULL OR PROP = 0 THEN
      L_PROP := TASK_PROP_TASK;
    ELSE
      L_PROP := PROP;
    END IF;
    PARSE_NAME(TASK_NAME, PROP);
    IF (USER_ID = -1) THEN
       L_USER_ID := SYS_CONTEXT('USERENV', 'SESSION_USERID');
    ELSE
       L_USER_ID := USER_ID;
    END IF;
    SELECT ID INTO L_ID FROM SYS.WRI$_ADV_TASKS A
      WHERE A.NAME = TASK_NAME
        AND BITAND(A.PROPERTY, L_PROP) = L_PROP
        AND A.OWNER# = L_USER_ID;
    IF (ADVISOR_NAME IS NOT NULL) THEN
      SELECT T.ADVISOR_NAME INTO L_ADV_NAME FROM SYS.WRI$_ADV_TASKS T 
       WHERE ID = L_ID;
      IF (L_ADV_NAME <> ADVISOR_NAME) THEN
        SYS.DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOT_SUPPORTED);
      END IF;
    END IF;
    RETURN (L_ID);
    EXCEPTION 
      WHEN NO_DATA_FOUND THEN    
        IF PROP = TASK_PROP_WORKLOAD THEN
          BUF := FORMAT_MESSAGE(1, WRK_NOT_FOUND, TASK_NAME);
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ADVISOR_ERROR, BUF);
        ELSE
          DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(TASK_NOT_FOUND, TASK_NAME);
        END IF;
      WHEN OTHERS THEN
        RAISE;
  END VALIDATE_TASK;
PROCEDURE VALIDATE_TASK_ID(TASK_ID       IN  BINARY_INTEGER,
                           TASK_NAME     OUT VARCHAR2,
                           TASK_OWNER    OUT VARCHAR2,
                           TASK_OWNER_ID OUT NUMBER)
IS
BEGIN
  SELECT NAME, OWNER_NAME, OWNER#
  INTO   TASK_NAME, TASK_OWNER, TASK_OWNER_ID
  FROM   WRI$_ADV_TASKS
  WHERE  ID = TASK_ID;
EXCEPTION
  WHEN NO_DATA_FOUND THEN  
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(TASKID_NOT_FOUND, TASK_ID);
  WHEN OTHERS THEN
    RAISE;
END VALIDATE_TASK_ID;
PROCEDURE RECOVER_SINGLE_STALE_TASK(TASK_ID      IN NUMBER, 
                                    ACQUIRE_LOCK IN BOOLEAN := FALSE)
IS
  L_TASK_ID     NUMBER           := TASK_ID;
  L_TASK_STATUS BINARY_INTEGER;
  EXEC_NAME     VARCHAR2(30); 
  LOCK_ACQUIRED BOOLEAN := FALSE;
BEGIN
  IF (ACQUIRE_LOCK) THEN
    HANDLE_LOCK(L_TASK_ID, TASK_LOCK_X, 0);
    LOCK_ACQUIRED := TRUE; 
  END IF;
  SELECT STATUS#, LAST_EXECUTION INTO L_TASK_STATUS, EXEC_NAME
  FROM SYS.DBA_ADVISOR_TASKS
  WHERE TASK_ID = L_TASK_ID
  FOR UPDATE;
  IF (L_TASK_STATUS = TASK_STATE_EXEC) THEN
    UPDATE_EXECUTION(L_TASK_ID, EXEC_NAME, TASK_STATE_ERROR);
  END IF;
  IF (LOCK_ACQUIRED) THEN
    HANDLE_LOCK(L_TASK_ID, TASK_LOCK_R);
    LOCK_ACQUIRED := FALSE;
  END IF;
  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
    IF (LOCK_ACQUIRED) THEN
      HANDLE_LOCK(L_TASK_ID, TASK_LOCK_R);
      LOCK_ACQUIRED := FALSE;
    END IF;
    RAISE;
END RECOVER_SINGLE_STALE_TASK;
PROCEDURE RECOVER_STALE_TASKS
IS
   L_TASK_ID BINARY_INTEGER;
   L_LOCK_ACQUIRED BOOLEAN; 
   CURSOR EXEC_CANDIDATES_CUR IS
     SELECT TASK_ID
       FROM SYS.DBA_ADVISOR_TASKS
       WHERE STATUS# =  PRVT_ADVISOR.TASK_STATE_EXEC;
BEGIN
   OPEN EXEC_CANDIDATES_CUR;
   LOOP
      FETCH EXEC_CANDIDATES_CUR INTO L_TASK_ID;
      EXIT WHEN EXEC_CANDIDATES_CUR%NOTFOUND;
      BEGIN
         L_LOCK_ACQUIRED := FALSE;
         HANDLE_LOCK(L_TASK_ID, TASK_LOCK_X, 0);
         L_LOCK_ACQUIRED := TRUE;
         RECOVER_SINGLE_STALE_TASK(L_TASK_ID);
         IF(L_LOCK_ACQUIRED = TRUE) THEN
           HANDLE_LOCK(L_TASK_ID, TASK_LOCK_R);
         END IF;
      EXCEPTION
         WHEN OTHERS THEN
           IF(L_LOCK_ACQUIRED = TRUE) THEN
             HANDLE_LOCK(L_TASK_ID, TASK_LOCK_R);
           END IF;
           ROLLBACK;
           NULL;
      END;
   END LOOP;
   CLOSE EXEC_CANDIDATES_CUR;
  EXCEPTION
    WHEN OTHERS THEN
      IF(EXEC_CANDIDATES_CUR%ISOPEN) THEN
        CLOSE EXEC_CANDIDATES_CUR; 
      END IF;
      RAISE;
END RECOVER_STALE_TASKS;
PROCEDURE DELETE_EXPIRED_TASKS
IS
   L_TASK_ID BINARY_INTEGER;
   L_HAS_EXPIRED BOOLEAN;
   CURSOR DEL_TASK_CANDIDATES_CUR(IN_CURRENT_TIME DATE) IS
     SELECT T.TASK_ID
       FROM SYS.DBA_ADVISOR_TASKS T, WRI$_ADV_PARAMETERS P
       WHERE T.TASK_ID = P.TASK_ID AND
       T.STATUS# <> PRVT_ADVISOR.TASK_STATE_EXEC AND
       T.READ_ONLY = 'FALSE' AND
       P.NAME = 'DAYS_TO_EXPIRE' AND
             PRVT_ADVISOR.CHECK_EXPIRATION_COMP(IN_CURRENT_TIME, 
                                                T.LAST_MODIFIED, P.VALUE) = 1;
    CURSOR DEL_EXEC_CANDIDATES_CUR(IN_CURRENT_TIME DATE) IS
      SELECT T.TASK_ID, E.EXECUTION_NAME
        FROM SYS.DBA_ADVISOR_TASKS T, SYS.DBA_ADVISOR_EXECUTIONS E, 
             WRI$_ADV_PARAMETERS P
        WHERE T.TASK_ID = P.TASK_ID AND T.TASK_ID = E.TASK_ID AND
              T.STATUS# <> PRVT_ADVISOR.TASK_STATE_EXEC AND
              T.READ_ONLY = 'FALSE' AND
              P.NAME = 'EXECUTION_DAYS_TO_EXPIRE' AND
              PRVT_ADVISOR.CHECK_EXPIRATION_COMP(IN_CURRENT_TIME,
                                                 E.EXECUTION_LAST_MODIFIED,
                                                 P.VALUE) = 1;
BEGIN
   FOR REC IN DEL_TASK_CANDIDATES_CUR(SYSDATE) LOOP
      BEGIN
         COMMON_DELETE_TASK(REC.TASK_ID, NULL, DEL_OPT_EXPIRED + 
                                               DEL_OPT_NO_STATS);
         COMMIT;
      EXCEPTION
         WHEN OTHERS THEN
           ROLLBACK;
           NULL;
      END;
   END LOOP;
   FOR REC IN DEL_EXEC_CANDIDATES_CUR(SYSDATE) LOOP
      BEGIN
         COMMON_DELETE_TASK(REC.TASK_ID, REC.EXECUTION_NAME, DEL_OPT_EXPIRED + 
                                                             DEL_OPT_NO_STATS);
         COMMIT;
      EXCEPTION
         WHEN OTHERS THEN
           ROLLBACK;
           NULL;
      END;
   END LOOP;
END DELETE_EXPIRED_TASKS;
PROCEDURE SETUP_USER_ENVIRONMENT (ADVISOR_NAME    IN VARCHAR2)
  IS
    TP SYS.WRI$_ADV_ABSTRACT_T;
  BEGIN
    TP := VALIDATE_ADVISOR(ADVISOR_NAME);
    TP.SUB_USER_SETUP(TP.ADVISOR_ID);
  END SETUP_USER_ENVIRONMENT;
PROCEDURE DELETE_DIRECTIVE_I (DIRECTIVE_ID     IN BINARY_INTEGER,
                              INSTANCE_ID      IN BINARY_INTEGER,
                              TASK_ID          IN BINARY_INTEGER)
  AS
  EXTERNAL
  NAME "keadDeleteDirectivePLSQL"
  LIBRARY DBMS_KEA_LIB
  LANGUAGE C
  WITH CONTEXT
  PARAMETERS
  (CONTEXT,
   DIRECTIVE_ID UB4,
   INSTANCE_ID UB4,
   TASK_ID UB4
  );
PROCEDURE DELETE_DIRECTIVE (DIRECTIVE_ID    IN BINARY_INTEGER,
                            INSTANCE_NAME   IN VARCHAR2,
                            TASK_NAME       IN VARCHAR2 := NULL)
IS
  INSTANCE_ID BINARY_INTEGER;
  TASK_ID BINARY_INTEGER := 0;
  L_FLAGS BINARY_INTEGER;
BEGIN
  IF TASK_NAME IS NOT NULL AND LENGTH(TASK_NAME) > 0  AND TASK_NAME <> '0' THEN
    TASK_ID := VALIDATE_TASK(TASK_NAME);
    CHECK_MODIFY(TASK_NAME, TASK_ID);
    SELECT FLAGS INTO L_FLAGS
      FROM SYS.WRI$_ADV_DIRECTIVE_DEFS
      WHERE ID = DIRECTIVE_ID;
    IF BITAND(L_FLAGS,1) = 1 THEN
      CHECK_INITIAL(TASK_NAME, TASK_ID);
    END IF;
  END IF;
  VALIDATE_DIRECTIVE (DIRECTIVE_ID);
  INSTANCE_ID := LOOKUP_DIR_INSTANCE (DIRECTIVE_ID, INSTANCE_NAME, TASK_ID);
  IF INSTANCE_ID = 0 THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_DIRINST, INSTANCE_NAME); 
  END IF;
  DELETE_DIRECTIVE_I(DIRECTIVE_ID, INSTANCE_ID, TASK_ID);
  COMMIT;
END DELETE_DIRECTIVE;
PROCEDURE EVAL_DIRECTIVE_VALUE_I (DIRECTIVE_ID      IN BINARY_INTEGER,
                                  INSTANCE_ID       IN BINARY_INTEGER,
                                  TASK_ID           IN BINARY_INTEGER,
                                  P1                IN CLOB,
                                  P2                IN CLOB,
                                  OUT_BUF           IN OUT NOCOPY CLOB)
  IS
  EXTERNAL
  NAME "keadEvalDirectivePLSQL"
  LIBRARY DBMS_KEA_LIB
  LANGUAGE C
  WITH CONTEXT
  PARAMETERS
  (CONTEXT,
   DIRECTIVE_ID UB4,
   INSTANCE_ID UB4,
   TASK_ID UB4,
   P1 OCILOBLOCATOR,
   P1 INDICATOR SB2,
   P2 OCILOBLOCATOR,
   P2 INDICATOR SB2,
   OUT_BUF OCILOBLOCATOR,
   OUT_BUF INDICATOR SB2
  );
FUNCTION EVAL_DIRECTIVE (DIRECTIVE_ID      IN BINARY_INTEGER,
                         INSTANCE_NAME     IN VARCHAR2,
                         TASK_NAME         IN VARCHAR2,
                         P1                IN CLOB,
                         P2                IN CLOB)
  RETURN CLOB
  IS 
  BUFFER CLOB;
  INSTANCE_ID BINARY_INTEGER;
  TASK_ID BINARY_INTEGER := 0;
  L_FLAGS BINARY_INTEGER;
BEGIN
  IF TASK_NAME IS NOT NULL AND LENGTH(TASK_NAME) > 0  AND TASK_NAME <> '0' THEN
    TASK_ID := VALIDATE_TASK(TASK_NAME);
    CHECK_MODIFY(TASK_NAME, TASK_ID);
    SELECT FLAGS INTO L_FLAGS
      FROM SYS.WRI$_ADV_DIRECTIVE_DEFS
      WHERE ID = DIRECTIVE_ID;
    IF BITAND(L_FLAGS,1) = 1 THEN
      CHECK_INITIAL(TASK_NAME, TASK_ID);
    END IF;
  END IF;
  VALIDATE_DIRECTIVE (DIRECTIVE_ID);
  INSTANCE_ID := LOOKUP_DIR_INSTANCE (DIRECTIVE_ID, INSTANCE_NAME, TASK_ID);
  IF INSTANCE_ID = 0 THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_DIRINST, INSTANCE_NAME); 
  END IF;
  BUFFER := ' ';
  EVAL_DIRECTIVE_VALUE_I (DIRECTIVE_ID, INSTANCE_ID, TASK_ID, P1, P2, BUFFER);
  COMMIT;
  RETURN (BUFFER);
END EVAL_DIRECTIVE;
PROCEDURE INSERT_DIRECTIVE_I (DIRECTIVE_ID      IN BINARY_INTEGER,
                              INSTANCE_NAME     IN VARCHAR2,
                              TASK_ID           IN BINARY_INTEGER,
                              DOCUMENT          IN CLOB)
  IS
  EXTERNAL
  NAME "keadInsertDirectivePLSQL"
  LIBRARY DBMS_KEA_LIB
  LANGUAGE C
  WITH CONTEXT
  PARAMETERS
  (CONTEXT,
   DIRECTIVE_ID UB4,
   INSTANCE_NAME OCISTRING,
   INSTANCE_NAME INDICATOR SB2,
   TASK_ID UB4,
   DOCUMENT OCILOBLOCATOR,
   DOCUMENT INDICATOR SB2
  );
PROCEDURE INSERT_DIRECTIVE (DIRECTIVE_ID    IN BINARY_INTEGER,
                            INSTANCE_NAME   IN VARCHAR2,
                            TASK_NAME       IN VARCHAR2,
                            DOCUMENT        IN CLOB)
  IS
  L_CNT BINARY_INTEGER;
  L_TASK_ID BINARY_INTEGER := 0;
  INSTANCE_ID BINARY_INTEGER;
  L_FLAGS BINARY_INTEGER;
BEGIN
  IF INSTANCE_NAME IS NULL THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INVALID_TASK_NAME, 'NULL');
  END IF;
  SELECT FLAGS INTO L_FLAGS
    FROM SYS.WRI$_ADV_DIRECTIVE_DEFS
    WHERE ID = DIRECTIVE_ID;
  IF TASK_NAME IS NOT NULL AND LENGTH(TASK_NAME) > 0 AND TASK_NAME <> '0' THEN
    L_TASK_ID := VALIDATE_TASK(TASK_NAME);
    CHECK_MODIFY(TASK_NAME, L_TASK_ID);
    IF BITAND(L_FLAGS,1) = 1 THEN
      CHECK_INITIAL(TASK_NAME, L_TASK_ID);
    END IF;
  END IF;
  VALIDATE_DIRECTIVE (DIRECTIVE_ID);
  INSTANCE_ID := LOOKUP_DIR_INSTANCE (DIRECTIVE_ID, INSTANCE_NAME, L_TASK_ID);
  IF INSTANCE_ID > 0 THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(DIRINST_EXISTS, INSTANCE_NAME); 
  END IF;
  IF BITAND(L_FLAGS,2) = 0 THEN
    SELECT COUNT(*) INTO L_CNT
      FROM SYS.WRI$_ADV_DIRECTIVE_INSTANCES
      WHERE DIR_ID = DIRECTIVE_ID
        AND TASK_ID = L_TASK_ID;
    IF L_CNT > 0 THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(DIRINST_MAX); 
    END IF;
  END IF;
  INSERT_DIRECTIVE_I (DIRECTIVE_ID, INSTANCE_NAME, L_TASK_ID, DOCUMENT);
  COMMIT;
END INSERT_DIRECTIVE;
PROCEDURE UPDATE_DIRECTIVE_I (DIRECTIVE_ID     IN BINARY_INTEGER,
                              INSTANCE_ID      IN BINARY_INTEGER,
                              TASK_ID          IN BINARY_INTEGER,
                              IN_BUF           IN CLOB)
  IS
  EXTERNAL
  NAME "keadUpdateDirectivePLSQL"
  LIBRARY DBMS_KEA_LIB
  LANGUAGE C
  WITH CONTEXT
  PARAMETERS
  (CONTEXT,
   DIRECTIVE_ID UB4,
   INSTANCE_ID UB4,
   TASK_ID UB4,
   IN_BUF OCILOBLOCATOR,
   IN_BUF INDICATOR SB2
  );
PROCEDURE UPDATE_DIRECTIVE (DIRECTIVE_ID   IN BINARY_INTEGER,
                            INSTANCE_NAME  IN VARCHAR2,
                            TASK_NAME      IN VARCHAR2,
                            DOCUMENT       IN CLOB)
  IS
  TASK_ID BINARY_INTEGER := 0;
  L_FLAGS BINARY_INTEGER;
  INSTANCE_ID BINARY_INTEGER;
BEGIN
  IF TASK_NAME IS NOT NULL AND LENGTH(TASK_NAME) > 0  AND TASK_NAME <> '0' THEN
    TASK_ID := VALIDATE_TASK(TASK_NAME);
    CHECK_MODIFY(TASK_NAME, TASK_ID);
    SELECT FLAGS INTO L_FLAGS
      FROM SYS.WRI$_ADV_DIRECTIVE_DEFS
      WHERE ID = DIRECTIVE_ID;
    IF BITAND(L_FLAGS,1) = 1 THEN
      CHECK_INITIAL(TASK_NAME, TASK_ID);
    END IF;
  END IF;
  VALIDATE_DIRECTIVE (DIRECTIVE_ID);
  INSTANCE_ID := LOOKUP_DIR_INSTANCE (DIRECTIVE_ID, INSTANCE_NAME, TASK_ID);
  IF INSTANCE_ID = 0 THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_DIRINST, INSTANCE_NAME); 
  END IF;
  UPDATE_DIRECTIVE_I (DIRECTIVE_ID, INSTANCE_ID, TASK_ID, DOCUMENT);
  COMMIT;
END UPDATE_DIRECTIVE;
PROCEDURE INSERT_ADV_DIR_DEF_I (L_ADV_ID      BINARY_INTEGER,
                                L_NAME        VARCHAR2,
                                L_DOMAIN      VARCHAR2,
                                L_DESCRIP     VARCHAR2,
                                L_TYPE        BINARY_INTEGER,
                                L_FLAGS       BINARY_INTEGER)
  IS
  EXTERNAL
  NAME "keadInsertDirDefPLSQL"
  LIBRARY DBMS_KEA_LIB
  LANGUAGE C
  WITH CONTEXT
  PARAMETERS
  (CONTEXT,
   L_ADV_ID UB4,
   L_NAME OCISTRING,
   L_NAME INDICATOR SB2,
   L_DOMAIN OCISTRING,
   L_DOMAIN INDICATOR SB2,
   L_DESCRIP OCISTRING,
   L_DESCRIP INDICATOR SB2,
   L_TYPE UB4,
   L_FLAGS UB4
  );
PROCEDURE UPDATE_ADV_DIR_DEF_I (L_ID          BINARY_INTEGER,
                                L_DESCRIP     VARCHAR2,
                                L_FLAGS       BINARY_INTEGER)
  IS
  EXTERNAL
  NAME "keadUpdateDirDefPLSQL"
  LIBRARY DBMS_KEA_LIB
  LANGUAGE C
  WITH CONTEXT
  PARAMETERS
  (CONTEXT,
   L_ID UB4,
   L_DESCRIP OCISTRING,
   L_DESCRIP INDICATOR SB2,
   L_FLAGS UB4
  );
PROCEDURE INSERT_ADV_DIR_DEF (L_ADV_ID      BINARY_INTEGER,
                              L_NAME        VARCHAR2,
                              L_DOMAIN      VARCHAR2,
                              L_DESCRIP     VARCHAR2,
                              L_TYPE        BINARY_INTEGER,
                              L_FLAGS       BINARY_INTEGER)
  IS
  L_CNT BINARY_INTEGER;
  L_ADV_NAME VARCHAR2(30);
  L_ID BINARY_INTEGER;
  OLD_TYPE BINARY_INTEGER;
BEGIN
  IF L_ADV_ID IS NULL OR L_ADV_ID = 0 THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'Advisor ID');
  END IF;
  IF L_NAME IS NULL OR LENGTH(L_NAME) = 0 THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'Directive name');
  END IF;
  IF L_TYPE < 1 OR L_TYPE > 5 THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(INV_ARG, 'Directive type');
  END IF;
  SELECT COUNT(*) INTO L_CNT
    FROM SYS.WRI$_ADV_DEFINITIONS
    WHERE ID = L_ADV_ID;
  IF L_CNT = 0 THEN
    DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(ADVISOR_NOT_FOUND, L_ADV_ID);
  END IF;
  SELECT COUNT(*) INTO L_CNT
    FROM SYS.WRI$_ADV_DIRECTIVE_DEFS
    WHERE DOMAIN = L_DOMAIN
      AND NAME = L_NAME
      AND ADVISOR_ID = L_ADV_ID;
  IF L_CNT > 0 THEN
    SELECT ID,TYPE# INTO L_ID, OLD_TYPE
      FROM SYS.WRI$_ADV_DIRECTIVE_DEFS
    WHERE DOMAIN = L_DOMAIN
      AND NAME = L_NAME
      AND ADVISOR_ID = L_ADV_ID;
    IF OLD_TYPE <> L_TYPE THEN
      SELECT NAME INTO L_ADV_NAME
        FROM SYS.WRI$_ADV_DEFINITIONS
        WHERE ID = L_ADV_ID;
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(DIRECTIVE_EXISTS, 
                                        L_DOMAIN, L_NAME, L_ADV_NAME);
    END IF;
    UPDATE_ADV_DIR_DEF_I (L_ID, L_DESCRIP, L_FLAGS);
  ELSE
    INSERT_ADV_DIR_DEF_I (L_ADV_ID, L_NAME, L_DOMAIN, L_DESCRIP, L_TYPE,
                          L_FLAGS);
  END IF;
  COMMIT;
END INSERT_ADV_DIR_DEF;
FUNCTION GET_DIRECTIVE_ID (ADVISOR_NAME   IN VARCHAR2,
                           DIRECTIVE_NAME IN VARCHAR2)
RETURN BINARY_INTEGER
  IS
  L_DIR_ID BINARY_INTEGER    := 0;
  AN       VARCHAR2(32767)   := ADVISOR_NAME;
  DN       VARCHAR2(32767)   := DIRECTIVE_NAME;
BEGIN
  IF ADVISOR_NAME IS NULL OR DIRECTIVE_NAME IS NULL THEN
    RETURN -1;
  END IF;
  SELECT ID
    INTO L_DIR_ID
    FROM DBA_ADVISOR_DIR_DEFINITIONS
   WHERE ADVISOR_NAME = AN 
     AND DIRECTIVE_NAME = DN;
  RETURN L_DIR_ID;
  EXCEPTION 
    WHEN NO_DATA_FOUND THEN    
      RETURN -1;
    WHEN OTHERS THEN RAISE;
END GET_DIRECTIVE_ID;
FUNCTION FINDING_NAME_EXISTS(ADVISOR_NAME VARCHAR2,
                             FINDING_NAME VARCHAR2)
RETURN BOOLEAN
IS 
  CNT NUMBER;
  AN  VARCHAR2(32767) := ADVISOR_NAME;
  FN  VARCHAR2(32767) := FINDING_NAME;
BEGIN 
  IF ADVISOR_NAME IS NULL OR FINDING_NAME IS NULL THEN
    RETURN FALSE;
  END IF;
  SELECT COUNT(*) 
  INTO   CNT
  FROM   DBA_ADVISOR_FINDING_NAMES A
  WHERE  A.ADVISOR_NAME = AN
    AND  A.FINDING_NAME = FN; 
  IF (CNT = 0) THEN
    RETURN FALSE;
  END IF;   
  RETURN TRUE;
END FINDING_NAME_EXISTS; 
FUNCTION GENERATE_UNIQUE_NAME(
  TARGET_TYPE   IN  VARCHAR2,
  TARGET_PREFIX IN  VARCHAR2, 
  TARGET_ID     IN  NUMBER,
  TARGET_SUB_ID IN  NUMBER    := NULL,
  TARGET_OWNER  IN  NUMBER    := NULL, 
  TARGET_PROP   IN  NUMBER    := NULL,
  NEW_NAME      OUT VARCHAR2)
RETURN BOOLEAN
IS
   PREFIX   VARCHAR2(30);
   CNT      NUMBER;
   SUFFIX   NUMBER;
   QUERY    VARCHAR2(32767); 
BEGIN
   CASE TARGET_TYPE
     WHEN 'TASK' THEN 
       QUERY := 'SELECT count(*) FROM sys.wri$_adv_tasks a
                 WHERE a.name = :task_name AND 
                       bitand(a.property, ' || TARGET_PROP || ') <> 0 AND ' ||
                      'a.owner# = ' || TARGET_OWNER;
       NEW_NAME := TARGET_PREFIX || '_' || TARGET_ID;
     WHEN 'EXECUTION' THEN 
       IF (TARGET_SUB_ID IS NULL) THEN
         RAISE_APPLICATION_ERROR(
           -20000, 'TARGET_SUB_ID must be specified for generating exec names',
           TRUE);
       END IF;
       QUERY := 'SELECT count(*) FROM sys.wri$_adv_executions e
                 WHERE e.name = :exec_name and e.task_id = ' || TARGET_ID;
       NEW_NAME := TARGET_PREFIX || '_' || TARGET_SUB_ID;
     WHEN 'STS' THEN 
       QUERY := 'SELECT count(*) FROM sys.wri$_sqlset_definitions wd 
                 WHERE wd.name = :sts_name';       
       NEW_NAME := TARGET_PREFIX || '_' || TARGET_ID;
     ELSE 
       RAISE_APPLICATION_ERROR(
         -20000, 'The specified target ' || TARGET_TYPE || ' does not exist', 
         TRUE);
   END CASE; 
   IF (LENGTHB(NEW_NAME) > 25) THEN
     NEW_NAME := SUBSTRB(NEW_NAME, 1, 25); 
   END IF;
   PREFIX := NEW_NAME || '_';
   SUFFIX := 1;
   LOOP
      EXECUTE IMMEDIATE QUERY
      INTO CNT
      USING NEW_NAME;
      EXIT WHEN CNT = 0;
      NEW_NAME := PREFIX || SUFFIX;
      SUFFIX := SUFFIX + 1;
      IF (SUFFIX > 10000 OR LENGTHB(NEW_NAME) > 30) THEN
        RETURN FALSE; 
      END IF;
    END LOOP;
    RETURN TRUE;
  END GENERATE_UNIQUE_NAME;
  FUNCTION VALIDATE_EXECUTION_ID(TASK_ID      IN BINARY_INTEGER,
                                 TASK_NAME    IN VARCHAR2, 
                                 EXECUTION_ID IN BINARY_INTEGER)
  RETURN VARCHAR2
  IS
    EXEC_NAME VARCHAR2(30);
  BEGIN
    IF (EXECUTION_ID IS NULL) THEN
      EXEC_NAME := GET_LAST_EXECUTION(TASK_ID);
      IF (EXEC_NAME IS NULL) THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(NOEXEC_RESULTS, TASK_NAME);
      END IF;
    ELSE  
      SELECT MAX(EXECUTION_NAME)
      INTO   EXEC_NAME
      FROM   DBA_ADVISOR_EXECUTIONS E
      WHERE  E.TASK_ID = VALIDATE_EXECUTION_ID.TASK_ID AND
             E.EXECUTION_ID = VALIDATE_EXECUTION_ID.EXECUTION_ID;
      IF (EXEC_NAME IS NULL) THEN
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXECID_NOT_FOUND, EXECUTION_ID);
      END IF; 
    END IF;
    RETURN EXEC_NAME;
  END VALIDATE_EXECUTION_ID;
  FUNCTION VALIDATE_EXECUTION_OBJECT(TASK_NAME      IN VARCHAR2,
                                     TASK_ID_NUM    IN BINARY_INTEGER,
                                     EXECUTION_NAME IN VARCHAR2, 
                                     OBJECT_ID      IN BINARY_INTEGER)
  RETURN VARCHAR2
  IS
    EXEC_NAME VARCHAR2(32767) := EXECUTION_NAME;
    COUNTER   NUMBER; 
  BEGIN
    IF (OBJECT_ID IS NULL) THEN 
      RETURN VALIDATE_EXECUTION(TASK_ID_NUM, EXEC_NAME);
    ELSIF (EXECUTION_NAME IS NOT NULL) THEN 
      SELECT COUNT(*) INTO  COUNTER FROM WRI$_ADV_OBJECTS 
      WHERE TASK_ID = TASK_ID_NUM AND ID = OBJECT_ID AND 
            NVL(EXEC_NAME, EXECUTION_NAME) = EXECUTION_NAME; 
      IF (COUNTER = 0) THEN 
        DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXECOBJ_NOT_FOUND);
      END IF;
    ELSE 
      SELECT EXEC_NAME INTO EXEC_NAME FROM WRI$_ADV_OBJECTS 
      WHERE TASK_ID = TASK_ID_NUM AND ID = OBJECT_ID; 
      IF (EXEC_NAME IS NOT NULL AND LENGTH(EXEC_NAME) != 0) THEN 
        RETURN EXEC_NAME; 
      ELSE
        RETURN GET_LAST_EXECUTION(TASK_ID_NUM); 
      END IF; 
    END IF;
    RETURN EXEC_NAME; 
    EXCEPTION 
      WHEN NO_DATA_FOUND THEN    
       DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(OBJECT_NOT_FOUND, 
                                         OBJECT_ID, TASK_NAME);
      WHEN OTHERS THEN
      RAISE;
  END VALIDATE_EXECUTION_OBJECT;
PROCEDURE VALIDATE_EXECUTION_ORDER(TID        IN NUMBER, 
                                   BEGIN_EXEC IN VARCHAR2,
                                   END_EXEC   IN VARCHAR2)
IS
  CNT NUMBER;
BEGIN
  IF (BEGIN_EXEC <> END_EXEC) THEN
    SELECT COUNT(*)
    INTO   CNT
    FROM   DBA_ADVISOR_EXECUTIONS E1, DBA_ADVISOR_EXECUTIONS E2
    WHERE  E1.TASK_ID = TID AND E1.EXECUTION_NAME = BEGIN_EXEC AND
           E2.TASK_ID = TID AND E2.EXECUTION_NAME = END_EXEC AND
           E2.EXECUTION_START < E1.EXECUTION_START; 
    IF (CNT <> 0) THEN
      DBMS_SYS_ERROR.RAISE_SYSTEM_ERROR(EXECS_OUT_OF_ORDER);
    END IF;
  END IF;
END VALIDATE_EXECUTION_ORDER;
FUNCTION  INSERT_MESSAGE (TASKID IN NUMBER,  FIND_SIMILAR IN BOOLEAN,
                          ENAME IN VARCHAR,
                          FACILITY IN VARCHAR, MSG_NUM IN NUMBER,
                          ARG1 IN VARCHAR := NULL, 
                          ARG2 IN VARCHAR := NULL, 
                          ARG3 IN VARCHAR := NULL, 
                          ARG4 IN VARCHAR := NULL, 
                          ARG5 IN VARCHAR := NULL,
                          HEADER IN NUMBER := 0,
                          MLM IN NUMBER := 0,
                          MNL IN NUMBER := 0,
                          MSEQ IN NUMBER := 0)
RETURN NUMBER
IS
  MSG_ID NUMBER := 0;
  CURSOR SIM_MSG(TASKID NUMBER, FACILITY VARCHAR,
                 MSG# NUMBER, ARG1 VARCHAR, ARG2 VARCHAR, 
                 ARG3 VARCHAR, ARG4 VARCHAR, ARG5 VARCHAR) IS
  SELECT ID 
  FROM   WRI$_ADV_MESSAGE_GROUPS
  WHERE  TASK_ID = TASKID
    AND  SEQ = 0
    AND  MESSAGE# = MSG_NUM
    AND  FAC = FACILITY
    AND  HDR = 0
    AND  LM = 0
    AND  NL = 0
    AND  EXEC_NAME = ENAME
    AND  NVL(ARG1, '~') = NVL(P1, '~')
    AND  NVL(ARG2, '~') = NVL(P2, '~')
    AND  NVL(ARG3, '~') = NVL(P3, '~')
    AND  NVL(ARG4, '~') = NVL(P4, '~')
    AND  NVL(ARG5, '~') = NVL(P5, '~');
BEGIN
  IF FIND_SIMILAR THEN
    FOR M IN SIM_MSG(TASKID, FACILITY, MSG_NUM, ARG1, ARG2, ARG3, ARG4, ARG5) LOOP
      MSG_ID := M.ID;
    END LOOP;
  END IF;
  IF MSG_ID = 0 THEN
    SELECT WRI$_ADV_SEQ_MSGGROUP.NEXTVAL INTO MSG_ID FROM DUAL;
    INSERT INTO WRI$_ADV_MESSAGE_GROUPS
      (TASK_ID, ID, EXEC_NAME, SEQ, MESSAGE#, FAC, HDR, LM, NL, P1, P2, P3, P4, P5)
    VALUES (
      TASKID, 
      MSG_ID, 
      ENAME,
      MSEQ, 
      MSG_NUM, 
      FACILITY, 
      HEADER, 
      MLM, 
      MNL,
      ARG1, 
      ARG2, 
      ARG3, 
      ARG4, 
      ARG5
    );
  END IF;
  RETURN MSG_ID;
END;
PROCEDURE INSERT_FINDING (TASK_ID IN NUMBER, FINDING_ID IN NUMBER,
                          ENAME IN VARCHAR,
                          FTYPE IN NUMBER, FPARENT IN NUMBER,
                          OBJ_ID IN NUMBER, IMPACT IN NUMBER, 
                          IMPACT_MSG_ID IN NUMBER, FIND_MSG_ID IN NUMBER,
                          INFO_MSG_ID IN NUMBER, NAME_MSG_CODE IN VARCHAR)
IS
BEGIN
  INSERT INTO WRI$_ADV_FINDINGS
    (ID, TASK_ID, EXEC_NAME, TYPE, PARENT, OBJ_ID, IMPACT_MSG_ID, IMPACT_VAL, 
     MSG_ID, MORE_INFO_ID, NAME_MSG_CODE )
  VALUES (
    FINDING_ID, TASK_ID, ENAME, FTYPE, FPARENT, OBJ_ID, NVL(IMPACT_MSG_ID,0), IMPACT,
    NVL(FIND_MSG_ID,0), NVL(INFO_MSG_ID,0), NAME_MSG_CODE 
  );
END;
PROCEDURE INSERT_REC_ACT (TASK_ID IN NUMBER, FINDING_ID IN NUMBER,
                          ENAME IN VARCHAR,
                          REC_ID IN NUMBER, BENEFIT IN NUMBER, 
                          BENEFIT_MSG IN NUMBER, REC_TYPE IN VARCHAR,
                          ACT_ID IN NUMBER, ACT_MESSAGE IN NUMBER,
                          COMMAND_ID IN NUMBER,
                          ATTR1 IN VARCHAR, ATTR2 IN VARCHAR, 
                          ATTR3 IN VARCHAR)
IS
  TID NUMBER;
  FID NUMBER;
  RID NUMBER;
  AID NUMBER;
  CID NUMBER;
BEGIN
  TID := TASK_ID;
  FID := FINDING_ID;
  RID := REC_ID;
  AID := ACT_ID;
  CID := COMMAND_ID;
  UPDATE WRI$_ADV_TASKS T
  SET    T.REC_COUNT = T.REC_COUNT + 1
  WHERE  T.ID = TID;
  INSERT INTO WRI$_ADV_RECOMMENDATIONS
    (TASK_ID, FINDING_ID, EXEC_NAME, 
     ID, TYPE, RANK, BENEFIT_VAL, BENEFIT_MSG_ID, FLAGS, FILTERED)
  VALUES
    (TID, FID, ENAME, 
     RID, REC_TYPE, 1, BENEFIT, BENEFIT_MSG, 0, 'N');
  INSERT INTO WRI$_ADV_ACTIONS
    (TASK_ID, EXEC_NAME, 
     ID, COMMAND, FLAGS, MSG_ID, FILTERED,
     ATTR1, ATTR2, ATTR3)
  VALUES
    (TID, ENAME,
     AID, CID, 0, ACT_MESSAGE, 'N', 
     INSERT_REC_ACT.ATTR1, INSERT_REC_ACT.ATTR2, 
     INSERT_REC_ACT.ATTR3);
  INSERT INTO WRI$_ADV_REC_ACTIONS
    (TASK_ID, REC_ID, ACT_ID)
  VALUES (TID, RID, AID);
END;
FUNCTION IS_PACK_ENABLED(PACK_NAME IN VARCHAR2)
RETURN BOOLEAN
IS
BEGIN
  RETURN PRVT_SMGUTIL.IS_PACK_ENABLED(PACK_NAME);
END;
PROCEDURE CHECK_PACK_ENABLED(PACK_NAME IN VARCHAR2)
IS
BEGIN
  PRVT_SMGUTIL.CHECK_PACK_ENABLED(PACK_NAME);
END;
PROCEDURE CHECK_ADV_ENABLED(ADV_ID IN NUMBER)
IS
BEGIN
  CASE ADV_ID
  WHEN DBMS_ADVISOR.ADV_ID_ADDM THEN
    CHECK_PACK_ENABLED(DBMS_MANAGEMENT_PACKS.DIAGNOSTIC_PACK);
  WHEN DBMS_ADVISOR.ADV_ID_SQLTUNE THEN
    CHECK_PACK_ENABLED(DBMS_MANAGEMENT_PACKS.TUNING_PACK);
  WHEN DBMS_ADVISOR.ADV_ID_SQLACCESS THEN
    CHECK_PACK_ENABLED(DBMS_MANAGEMENT_PACKS.TUNING_PACK);
  WHEN DBMS_ADVISOR.ADV_ID_SQLPA THEN
    PRVT_SMGUTIL.CHECK_RAT_OPTION;
  ELSE 
    RETURN; 
  END CASE;
END;
PROCEDURE CHECK_ADV_ENABLED(ADV_NAME IN VARCHAR2)
IS
BEGIN
  CASE ADV_NAME 
  WHEN DBMS_ADVISOR.ADV_NAME_ADDM THEN
    CHECK_PACK_ENABLED(DBMS_MANAGEMENT_PACKS.DIAGNOSTIC_PACK);
  WHEN DBMS_ADVISOR.ADV_NAME_SQLACCESS THEN 
    CHECK_PACK_ENABLED(DBMS_MANAGEMENT_PACKS.TUNING_PACK);
  WHEN DBMS_ADVISOR.ADV_NAME_SQLTUNE THEN
    CHECK_PACK_ENABLED(DBMS_MANAGEMENT_PACKS.TUNING_PACK);
  WHEN DBMS_ADVISOR.ADV_NAME_SQLPA THEN
    PRVT_SMGUTIL.CHECK_RAT_OPTION;
  ELSE 
    RETURN; 
  END CASE;
END;
PROCEDURE CHECK_TASK_ENABLED(TASK_NAME   IN VARCHAR2,
                             ADV_NAME    IN VARCHAR2 := NULL,
                             CREATE_TASK IN BOOLEAN := FALSE)
IS
  ANAME  VARCHAR2(30) := ADV_NAME;
BEGIN
  IF TASK_NAME IS NULL AND ANAME IS NULL THEN
    RETURN;
  END IF;
  IF ANAME IS NULL THEN
    SELECT MAX(ADVISOR_NAME)  
    INTO ANAME 
    FROM WRI$_ADV_TASKS
    WHERE NAME = TASK_NAME;   
  END IF;
  IF ANAME IS NULL THEN
    RETURN;
  END IF;
  IF (TASK_NAME = TASK_RESERVED_NAME_ASQLT 
      AND ANAME = DBMS_ADVISOR.ADV_NAME_SQLTUNE
      AND CREATE_TASK) THEN
    RETURN;
  END IF;
  CHECK_ADV_ENABLED(ANAME);
END;
FUNCTION ADJUST_STRING(STR IN VARCHAR2, MAX_LEN IN NUMBER) 
RETURN VARCHAR2 
AS   
BEGIN 
  IF (MAX_LEN > 0 AND  LENGTH(STR) > MAX_LEN) THEN 
    RETURN (SUBSTR(STR, 0, MAX_LEN - 3) || '...'); 
  END IF; 
  RETURN STR; 
END ADJUST_STRING; 
PROCEDURE TRACK_REPORT_USAGE(ADVISOR_ID IN NUMBER)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  UPDATE SYS.WRI$_ADV_USAGE U
     SET NUM_DB_REPORTS = U.NUM_DB_REPORTS + 1,
         FIRST_REPORT_TIME = NVL(U.FIRST_REPORT_TIME, SYSDATE),
         LAST_REPORT_TIME = SYSDATE  
   WHERE U.ADVISOR_ID = TRACK_REPORT_USAGE.ADVISOR_ID;
  COMMIT;
  EXCEPTION     
    WHEN OTHERS THEN
       IF SQLCODE <> -16000 THEN 
        DBMS_SYSTEM.KSDWRT(1, 'ERROR in feature usage recording of advisor '
                           || ADVISOR_ID || ': '
                           || SQLERRM);
       END IF;        
END TRACK_REPORT_USAGE;
END PRVT_ADVISOR;

 

你可能感兴趣的:(saa内部解析:PACKAGE BODY prvt_advisor)