/**
   * This is the guts of the Execution-time logic for DROP ROLE.
   *
   * @see org.apache.derby.iapi.sql.execute.ConstantAction#executeConstantAction
   */
  public void executeConstantAction(Activation activation) throws StandardException {
    LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
    DataDictionary dd = lcc.getDataDictionary();
    TransactionController tc = lcc.getTransactionExecute();

    /*
     ** Inform the data dictionary that we are about to write to it.
     ** There are several calls to data dictionary "get" methods here
     ** that might be done in "read" mode in the data dictionary, but
     ** it seemed safer to do this whole operation in "write" mode.
     **
     ** We tell the data dictionary we're done writing at the end of
     ** the transaction.
     */
    dd.startWriting(lcc);

    RoleGrantDescriptor rdDef = dd.getRoleDefinitionDescriptor(roleName);

    if (rdDef == null) {
      throw StandardException.newException(SQLState.ROLE_INVALID_SPECIFICATION, roleName);
    }

    // When a role is dropped, for every role in its grantee closure, we
    // call the REVOKE_ROLE action. It is used to invalidate dependent
    // objects (constraints, triggers and views).  Note that until
    // DERBY-1632 is fixed, we risk dropping objects not really dependent
    // on this role, but one some other role just because it inherits from
    // this one. See also RevokeRoleConstantAction.
    RoleClosureIterator rci =
        dd.createRoleClosureIterator(activation.getTransactionController(), roleName, false);

    String role;
    while ((role = rci.next()) != null) {
      RoleGrantDescriptor r = dd.getRoleDefinitionDescriptor(role);

      dd.getDependencyManager().invalidateFor(r, DependencyManager.REVOKE_ROLE, lcc);
    }

    rdDef.drop(lcc);

    /*
     * We dropped a role, now drop all dependents:
     * - role grants to this role
     * - grants of this role to other roles or users
     * - privilege grants to this role
     */

    dd.dropRoleGrantsByGrantee(roleName, tc);
    dd.dropRoleGrantsByName(roleName, tc);
    dd.dropAllPermsByGrantee(roleName, tc);
  }
  /**
   * This is the guts of the Execution-time logic for CREATE TRIGGER.
   *
   * @see ConstantAction#executeConstantAction
   * @exception StandardException Thrown on failure
   */
  public void executeConstantAction(Activation activation) throws StandardException {
    SPSDescriptor whenspsd = null;
    SPSDescriptor actionspsd;

    LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
    DataDictionary dd = lcc.getDataDictionary();
    DependencyManager dm = dd.getDependencyManager();
    TransactionController tc = lcc.getTransactionExecute();

    /*
     ** Indicate that we are about to modify the data dictionary.
     **
     ** We tell the data dictionary we're done writing at the end of
     ** the transaction.
     */
    dd.startWriting(lcc);

    SchemaDescriptor triggerSd = getSchemaDescriptorForCreate(dd, activation, triggerSchemaName);

    if (spsCompSchemaId == null) {
      SchemaDescriptor def = lcc.getDefaultSchema();
      if (def.getUUID() == null) {
        // Descriptor for default schema is stale,
        // look it up in the dictionary
        def = dd.getSchemaDescriptor(def.getDescriptorName(), tc, false);
      }

      /*
       ** It is possible for spsCompSchemaId to be null.  For instance,
       ** the current schema may not have been physically created yet but
       ** it exists "virtually".  In this case, its UUID will have the
       ** value of null meaning that it is not persistent.  e.g.:
       **
       ** CONNECT 'db;create=true' user 'ernie';
       ** CREATE TABLE bert.t1 (i INT);
       ** CREATE TRIGGER bert.tr1 AFTER INSERT ON bert.t1
       **    FOR EACH STATEMENT MODE DB2SQL
       **    SELECT * FROM SYS.SYSTABLES;
       **
       ** Note that in the above case, the trigger action statement have a
       ** null compilation schema.  A compilation schema with null value
       ** indicates that the trigger action statement text does not have
       ** any dependencies with the CURRENT SCHEMA.  This means:
       **
       ** o  It is safe to compile this statement in any schema since
       **    there is no dependency with the CURRENT SCHEMA. i.e.: All
       **    relevent identifiers are qualified with a specific schema.
       **
       ** o  The statement cache mechanism can utilize this piece of
       **    information to enable better statement plan sharing across
       **    connections in different schemas; thus, avoiding unnecessary
       **    statement compilation.
       */
      if (def != null) spsCompSchemaId = def.getUUID();
    }

    String tabName;
    if (triggerTable != null) {
      triggerTableId = triggerTable.getUUID();
      tabName = triggerTable.getName();
    } else tabName = "with UUID " + triggerTableId;

    /* We need to get table descriptor again.  We simply can't trust the
     * one we got at compile time, the lock on system table was released
     * when compile was done, and the table might well have been dropped.
     */
    triggerTable = dd.getTableDescriptor(triggerTableId);
    if (triggerTable == null) {
      throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tabName);
    }
    /* Lock the table for DDL.  Otherwise during our execution, the table
     * might be changed, even dropped.  Beetle 4269
     */
    lockTableForDDL(tc, triggerTable.getHeapConglomerateId(), true);
    /* get triggerTable again for correctness, in case it's changed before
     * the lock is aquired
     */
    triggerTable = dd.getTableDescriptor(triggerTableId);
    if (triggerTable == null) {
      throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tabName);
    }

    /*
     ** Send an invalidate on the table from which
     ** the triggering event emanates.  This it
     ** to make sure that DML statements on this table
     ** will be recompiled.  Do this before we create
     ** our trigger spses lest we invalidate them just
     ** after creating them.
     */
    dm.invalidateFor(triggerTable, DependencyManager.CREATE_TRIGGER, lcc);

    /*
     ** Lets get our trigger id up front, we'll use it when
     ** we create our spses.
     */
    UUID tmpTriggerId = dd.getUUIDFactory().createUUID();

    actionSPSId = (actionSPSId == null) ? dd.getUUIDFactory().createUUID() : actionSPSId;

    DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();

    /*
     ** Create the trigger descriptor first so the trigger action
     ** compilation can pick up the relevant trigger especially in
     ** the case of self triggering.
     */
    TriggerDescriptor triggerd =
        ddg.newTriggerDescriptor(
            triggerSd,
            tmpTriggerId,
            triggerName,
            eventMask,
            isBefore,
            isRow,
            isEnabled,
            triggerTable,
            whenspsd == null ? null : whenspsd.getUUID(),
            actionSPSId,
            creationTimestamp == null
                ? new Timestamp(System.currentTimeMillis())
                : creationTimestamp,
            referencedCols,
            originalActionText,
            referencingOld,
            referencingNew,
            oldReferencingName,
            newReferencingName);

    dd.addDescriptor(triggerd, triggerSd, DataDictionary.SYSTRIGGERS_CATALOG_NUM, false, tc);

    /*
     ** If we have a WHEN action we create it now.
     */
    if (whenText != null) {
      whenspsd =
          createSPS(
              lcc,
              ddg,
              dd,
              tc,
              tmpTriggerId,
              triggerSd,
              whenSPSId,
              spsCompSchemaId,
              whenText,
              true,
              triggerTable);
    }

    /*
     ** Create the trigger action
     */
    actionspsd =
        createSPS(
            lcc,
            ddg,
            dd,
            tc,
            tmpTriggerId,
            triggerSd,
            actionSPSId,
            spsCompSchemaId,
            actionText,
            false,
            triggerTable);

    /*
     ** Make underlying spses dependent on the trigger.
     */
    if (whenspsd != null) {
      dm.addDependency(triggerd, whenspsd, lcc.getContextManager());
    }
    dm.addDependency(triggerd, actionspsd, lcc.getContextManager());
    dm.addDependency(triggerd, triggerTable, lcc.getContextManager());
    dm.addDependency(actionspsd, triggerTable, lcc.getContextManager());
    // store trigger's dependency on various privileges in the dependeny system
    storeViewTriggerDependenciesOnPrivileges(activation, triggerd);
  }