Package org.apache.derby.iapi.sql.dictionary

Examples of org.apache.derby.iapi.sql.dictionary.TriggerDescriptor


        ** For now, we don't allow bulk insert replace when
        ** there is a trigger.
        */
        if (triggerInfo != null)
        {
          TriggerDescriptor td = triggerInfo.getTriggerArray()[0];
          throw StandardException.newException(SQLState.LANG_NO_BULK_INSERT_REPLACE_WITH_TRIGGER_DURING_EXECUTION, constants.getTableName(), td.getName());
        }
      }
    }

    //System.out.println("new InsertResultSet " + sourceResultSet.getClass());
View Full Code Here


      needsDeferredProcessing[0] = true;
     
      boolean needToIncludeAllColumns = false;
            for (Iterator descIter = relevantTriggers.iterator();
                    descIter.hasNext(); ) {
                TriggerDescriptor trd = (TriggerDescriptor)descIter.next();
        //Does this trigger have REFERENCING clause defined on it.
        //If yes, then read all the columns from the trigger table.
        if (!trd.getReferencingNew() && !trd.getReferencingOld())
          continue;
        else
        {
          needToIncludeAllColumns = true;
          break;
View Full Code Here

    //Now go through each trigger on this table and see if the column
    //being dropped is part of it's trigger columns or trigger action
    //columns which are used through REFERENCING clause
    GenericDescriptorList tdl = dd.getTriggerDescriptors(td);
        for (Iterator descIter = tdl.iterator(); descIter.hasNext() ; ) {
            TriggerDescriptor trd = (TriggerDescriptor)descIter.next();
      //If we find that the trigger is dependent on the column being
      //dropped because column is part of trigger columns list, then
      //we will give a warning or drop the trigger based on whether
      //ALTER TABLE DROP COLUMN is RESTRICT or CASCADE. In such a
      //case, no need to check if the trigger action columns referenced
      //through REFERENCING clause also used the column being dropped.
      boolean triggerDroppedAlready = false;

      int[] referencedCols = trd.getReferencedCols();
      if (referencedCols != null) {
        int refColLen = referencedCols.length, j;
        boolean changed = false;
        for (j = 0; j < refColLen; j++)
        {
          if (referencedCols[j] > droppedColumnPosition)
                  {
            //Trigger is not defined on the column being dropped
            //but the column position of trigger column is changing
            //because the position of the column being dropped is
            //before the the trigger column
            changed = true;
                  }
          else if (referencedCols[j] == droppedColumnPosition)
          {
            //the trigger is defined on the column being dropped
            if (cascade)
            {
                          trd.drop(lcc);
                          triggerDroppedAlready = true;
              activation.addWarning(
                StandardException.newWarning(
                                  SQLState.LANG_TRIGGER_DROPPED,
                                  trd.getName(), td.getName()));
            }
            else
            // we'd better give an error if don't drop it,
              // otherwsie there would be unexpected behaviors
              throw StandardException.newException(
                              SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                              dm.getActionString(DependencyManager.DROP_COLUMN),
                              columnName, "TRIGGER",
                              trd.getName() );
            }
            break;
          }
        }

        // The following if condition will be true if the column
        // getting dropped is not a trigger column, but one or more
        // of the trigge column's position has changed because of
        // drop column.
        if (j == refColLen && changed)
        {
          dd.dropTriggerDescriptor(trd, tc);
          for (j = 0; j < refColLen; j++)
          {
            if (referencedCols[j] > droppedColumnPosition)
              referencedCols[j]--;
          }
          dd.addDescriptor(trd, sd,
                   DataDictionary.SYSTRIGGERS_CATALOG_NUM,
                   false, tc);
        }
      }

      // If the trigger under consideration got dropped through the
      // loop above, then move to next trigger
      if (triggerDroppedAlready) continue;
     
      // Column being dropped is not one of trigger columns. Check if
      // that column is getting used inside the trigger action through
      // REFERENCING clause. This can be tracked only for triggers
      // created in 10.7 and higher releases. Derby releases prior to
      // that did not keep track of trigger action columns used
      // through the REFERENCING clause.
      int[] referencedColsInTriggerAction = trd.getReferencedColsInTriggerAction();
      if (referencedColsInTriggerAction != null) {
        int refColInTriggerActionLen = referencedColsInTriggerAction.length, j;
        boolean changedColPositionInTriggerAction = false;
        for (j = 0; j < refColInTriggerActionLen; j++)
        {
          if (referencedColsInTriggerAction[j] > droppedColumnPosition)
          {
            changedColPositionInTriggerAction = true;
          }
          else if (referencedColsInTriggerAction[j] == droppedColumnPosition)
          {
            if (cascade)
            {
                          trd.drop(lcc);
                          triggerDroppedAlready = true;
              activation.addWarning(
                StandardException.newWarning(
                                  SQLState.LANG_TRIGGER_DROPPED,
                                  trd.getName(), td.getName()));
            }
            else
            // we'd better give an error if don't drop it,
              throw StandardException.newException(
                              SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                              dm.getActionString(DependencyManager.DROP_COLUMN),
                              columnName, "TRIGGER",
                              trd.getName() );
            }
            break;
          }
        }

        // change trigger to refer to columns in new positions
        // The following if condition will be true if the column
        // getting dropped is not getting used in the trigger action
        // sql through the REFERENCING clause but one or more of those
        // column's position has changed because of drop column.
        // This applies only to triggers created with 10.7 and higher.
        // Prior to that, Derby did not keep track of the trigger
        // action column used through the REFERENCING clause. Such
        // triggers will be caught later on in this method after the
        // column has been actually dropped from the table descriptor.
        if (j == refColInTriggerActionLen && changedColPositionInTriggerAction)
        {
          dd.dropTriggerDescriptor(trd, tc);
          for (j = 0; j < refColInTriggerActionLen; j++)
          {
            if (referencedColsInTriggerAction[j] > droppedColumnPosition)
              referencedColsInTriggerAction[j]--;
          }
          dd.addDescriptor(trd, sd,
               DataDictionary.SYSTRIGGERS_CATALOG_NUM,
               false, tc);
        }
      }
    }

    ConstraintDescriptorList csdl = dd.getConstraintDescriptors(td);
    int csdl_size = csdl.size();

    ArrayList newCongloms = new ArrayList();

    // we want to remove referenced primary/unique keys in the second
    // round.  This will ensure that self-referential constraints will
    // work OK.
    int tbr_size = 0;
    ConstraintDescriptor[] toBeRemoved =
            new ConstraintDescriptor[csdl_size];

    // let's go downwards, don't want to get messed up while removing
    for (int i = csdl_size - 1; i >= 0; i--)
    {
      ConstraintDescriptor cd = csdl.elementAt(i);
      int[] referencedColumns = cd.getReferencedColumns();
      int numRefCols = referencedColumns.length, j;
      boolean changed = false;
      for (j = 0; j < numRefCols; j++)
      {
        if (referencedColumns[j] > droppedColumnPosition)
          changed = true;
        if (referencedColumns[j] == droppedColumnPosition)
          break;
      }
      if (j == numRefCols)      // column not referenced
      {
        if ((cd instanceof CheckConstraintDescriptor) && changed)
        {
          dd.dropConstraintDescriptor(cd, tc);
          for (j = 0; j < numRefCols; j++)
          {
            if (referencedColumns[j] > droppedColumnPosition)
              referencedColumns[j]--;
          }
          ((CheckConstraintDescriptor) cd).setReferencedColumnsDescriptor(new ReferencedColumnsDescriptorImpl(referencedColumns));
          dd.addConstraintDescriptor(cd, tc);
        }
        continue;
      }

      if (! cascade)
      {
        // Reject the DROP COLUMN, because there exists a constraint
        // which references this column.
        //
        throw StandardException.newException(
                        SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                        dm.getActionString(DependencyManager.DROP_COLUMN),
                        columnName, "CONSTRAINT",
                        cd.getConstraintName() );
      }

      if (cd instanceof ReferencedKeyConstraintDescriptor)
      {
        // restrict will raise an error in invalidate if referenced
        toBeRemoved[tbr_size++] = cd;
        continue;
      }

      // drop now in all other cases
      dm.invalidateFor(cd, DependencyManager.DROP_CONSTRAINT,
                  lcc);

      dropConstraint(cd, td, newCongloms, activation, lcc, true);
      activation.addWarning(
                StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
        cd.getConstraintName(), td.getName()));
    }

    for (int i = tbr_size - 1; i >= 0; i--)
    {
      ConstraintDescriptor cd = toBeRemoved[i];
      dropConstraint(cd, td, newCongloms, activation, lcc, false);

      activation.addWarning(
                StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
                cd.getConstraintName(), td.getName()));

      if (cascade)
      {
        ConstraintDescriptorList fkcdl = dd.getForeignKeys(cd.getUUID());
        for (int j = 0; j < fkcdl.size(); j++)
        {
          ConstraintDescriptor fkcd =
                        (ConstraintDescriptor) fkcdl.elementAt(j);

          dm.invalidateFor(fkcd,
                  DependencyManager.DROP_CONSTRAINT,
                  lcc);

          dropConstraint(fkcd, td,
            newCongloms, activation, lcc, true);

          activation.addWarning(
                        StandardException.newWarning(
                            SQLState.LANG_CONSTRAINT_DROPPED,
                fkcd.getConstraintName(),
                            fkcd.getTableDescriptor().getName()));
        }
      }

      dm.invalidateFor(cd, DependencyManager.DROP_CONSTRAINT, lcc);
      dm.clearDependencies(lcc, cd);
    }

    /* If there are new backing conglomerates which must be
     * created to replace a dropped shared conglomerate
     * (where the shared conglomerate was dropped as part
     * of a "drop constraint" call above), then create them
     * now.  We do this *after* dropping all dependent
     * constraints because we don't want to waste time
     * creating a new conglomerate if it's just going to be
     * dropped again as part of another "drop constraint".
     */
    createNewBackingCongloms(newCongloms, (long[])null);

        /*
         * The work we've done above, specifically the possible
         * dropping of primary key, foreign key, and unique constraints
         * and their underlying indexes, may have affected the table
         * descriptor. By re-reading the table descriptor here, we
         * ensure that the compressTable code is working with an
         * accurate table descriptor. Without this line, we may get
         * conglomerate-not-found errors and the like due to our
         * stale table descriptor.
         */
    td = dd.getTableDescriptor(tableId);

        compressTable();

    ColumnDescriptorList tab_cdl = td.getColumnDescriptorList();

    // drop the column from syscolumns
    dd.dropColumnDescriptor(td.getUUID(), columnName, tc);   
    ColumnDescriptor[] cdlArray =
            new ColumnDescriptor[size - columnDescriptor.getPosition()];

    // For each column in this table with a higher column position,
    // drop the entry from SYSCOLUMNS, but hold on to the column
    // descriptor and reset its position to adjust for the dropped
    // column. Then, re-add all those adjusted column descriptors
    // back to SYSCOLUMNS
    //
    for (int i = columnDescriptor.getPosition(), j = 0; i < size; i++, j++)
    {
      ColumnDescriptor cd = (ColumnDescriptor) tab_cdl.elementAt(i);
      dd.dropColumnDescriptor(td.getUUID(), cd.getColumnName(), tc);
      cd.setPosition(i);
      if (cd.isAutoincrement())
      {
        cd.setAutoinc_create_or_modify_Start_Increment(
            ColumnDefinitionNode.CREATE_AUTOINCREMENT);
      }

      cdlArray[j] = cd;
    }
    dd.addDescriptorArray(cdlArray, td,
                DataDictionary.SYSCOLUMNS_CATALOG_NUM, false, tc);

    // By this time, the column has been removed from the table descriptor.
    // Now, go through all the triggers and regenerate their trigger action
    // SPS and rebind the generated trigger action sql. If the trigger 
    // action is using the dropped column, it will get detected here. If
    // not, then we will have generated the internal trigger action sql
    // which matches the trigger action sql provided by the user.
    //
    // eg of positive test case
    // create table atdc_16_tab1 (a1 integer, b1 integer, c1 integer);
    // create table atdc_16_tab2 (a2 integer, b2 integer, c2 integer);
    // create trigger atdc_16_trigger_1
    //    after update of b1 on atdc_16_tab1
    //    REFERENCING NEW AS newt
    //    for each row
    //    update atdc_16_tab2 set c2 = newt.c1
    // The internal representation for the trigger action before the column
    // is dropped is as follows
    //    update atdc_16_tab2 set c2 =
    //   org.apache.derby.iapi.db.Factory::getTriggerExecutionContext().
    //   getONewRow().getInt(3)
    // After the drop column shown as below
    //   alter table DERBY4998_SOFT_UPGRADE_RESTRICT drop column c11
    // The above internal representation of tigger action sql is not
    // correct anymore because column position of c1 in atdc_16_tab1 has
    // now changed from 3 to 2. Following while loop will regenerate it and
    // change it to as follows
    //    update atdc_16_tab2 set c2 =
    //   org.apache.derby.iapi.db.Factory::getTriggerExecutionContext().
    //   getONewRow().getInt(2)
    //
    // We could not do this before the actual column drop, because the
    // rebind would have still found the column being dropped in the
    // table descriptor and hence use of such a column in the trigger
    // action rebind would not have been caught.

    //For the table on which ALTER TABLE is getting performed, find out
    // all the SPSDescriptors that use that table as a provider. We are
    // looking for SPSDescriptors that have been created internally for
    // trigger action SPSes. Through those SPSDescriptors, we will be
    // able to get to the triggers dependent on the table being altered
    //Following will get all the dependent objects that are using
    // ALTER TABLE table as provider
    List depsOnAlterTableList = dd.getProvidersDescriptorList(td.getObjectID().toString());
    for (Iterator depsOnAlterTableIterator = depsOnAlterTableList.listIterator();
      depsOnAlterTableIterator.hasNext();)
    {
      //Go through all the dependent objects on the table being altered
      DependencyDescriptor depOnAlterTableDesc =
        (DependencyDescriptor) depsOnAlterTableIterator.next();
      DependableFinder dependent = depOnAlterTableDesc.getDependentFinder();
      //For the given dependent, we are only interested in it if it is a
      // stored prepared statement.
      if (dependent.getSQLObjectType().equals(Dependable.STORED_PREPARED_STATEMENT))
      {
        //Look for all the dependent objects that are using this
        // stored prepared statement as provider. We are only
        // interested in dependents that are triggers.
        List depsTrigger = dd.getProvidersDescriptorList(depOnAlterTableDesc.getUUID().toString());
        for (Iterator depsTriggerIterator = depsTrigger.listIterator();
          depsTriggerIterator.hasNext();)
        {
          DependencyDescriptor depsTriggerDesc =
            (DependencyDescriptor) depsTriggerIterator.next();
          DependableFinder providerIsTrigger = depsTriggerDesc.getDependentFinder();
          //For the given dependent, we are only interested in it if
          // it is a trigger
          if (providerIsTrigger.getSQLObjectType().equals(Dependable.TRIGGER)) {
            //Drop and recreate the trigger after regenerating
            // it's trigger action plan. If the trigger action
            // depends on the column being dropped, it will be
            // caught here.
            TriggerDescriptor trdToBeDropped  = dd.getTriggerDescriptor(depsTriggerDesc.getUUID());
            columnDroppedAndTriggerDependencies(trdToBeDropped,
                cascade, columnName);
          }
        }
      }
View Full Code Here

    }

    //truncate is not allowed when there are enabled DELETE triggers
    GenericDescriptorList tdl = dd.getTriggerDescriptors(td);
        for (Iterator descIter = tdl.iterator(); descIter.hasNext(); ) {
            TriggerDescriptor trd = (TriggerDescriptor)descIter.next();
      if (trd.listensForEvent(TriggerDescriptor.TRIGGER_EVENT_DELETE) &&
        trd.isEnabled())
      {
        throw
          StandardException.newException(SQLState.LANG_NO_TRUNCATE_ON_ENABLED_DELETE_TRIGGERS,
                           td.getName(),trd.getName())
      }
    }

    //gather information from the existing conglomerate to create new one.
    emptyHeapRow = td.getEmptyExecRow();
View Full Code Here

    /*
    ** 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,
View Full Code Here

      // go back to the older release if that's what the user chooses
      // after the soft-upgrade.
      boolean in10_9_orHigherVersion = dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_9,null);
            for (Iterator descIter = relevantTriggers.iterator();
                    descIter.hasNext(); ) {
                TriggerDescriptor trd = (TriggerDescriptor) descIter.next();
        if (in10_9_orHigherVersion) {
          // See if we can avoid reading all the columns from the
          // trigger table.
                  int[] referencedColsInTriggerAction = trd.getReferencedColsInTriggerAction();
                  int[] triggerCols = trd.getReferencedCols();
                  if (triggerCols == null || triggerCols.length == 0) {
                          for (int i=0; i < columnCount; i++) {
                                  columnMap.set(i+1);
                          }
                          //This trigger is not defined on specific columns
                          // so we will have to read all the columns from the
                          // trigger table. Now, there is no need to go
                          // through the rest of the triggers because we are
                          // going to read all the columns anyways.
                          break;
                  } else {
                          if (referencedColsInTriggerAction == null ||
                                          referencedColsInTriggerAction.length == 0) {
                                  //Does this trigger have REFERENCING clause defined on it
                                  if (!trd.getReferencingNew() && !trd.getReferencingOld()) {
                                    //The trigger does not use trigger action columns through
                                    //the REFERENCING clause so we need to read just the
                                    //trigger columns
                                        for (int ix = 0; ix < triggerCols.length; ix++)
                                        {
                                                columnMap.set(triggerCols[ix]);
                                        }
                                  } else {
                                    //The trigger has REFERENCING clause defined on it
                                    // so it might be used them in trigger action.
                                    // We should just go ahead and read all the
                                    // columns from the trigger table. Now, there is
                                    // no need to go through the rest of the triggers
                                    // because we are going to read all the columns
                                    // anyways.
                                    needToIncludeAllColumns = true;
                                    break;
                                  }
                          } else {
                            //This trigger has both trigger columns and
                            // trigger action columns(getting used through
                            // the REFERENCING clause). Read only those
                            // columns because that's all we need from
                            // trigger table for the trigger execution.
                                  for (int ix = 0; ix < triggerCols.length; ix++)
                                  {
                                          columnMap.set(triggerCols[ix]);
                                  }
                                  for (int ix = 0; ix < referencedColsInTriggerAction.length; ix++)
                                  {
                                          columnMap.set(referencedColsInTriggerAction[ix]);
                                  }
                          }
                  }     
              } else {
                //We are in soft upgrade mode working with 10.8 or lower
                // database.
                  //Does this trigger have REFERENCING clause defined on it
                  if (!trd.getReferencingNew() && !trd.getReferencingOld())
                          continue;
                  else
                  {
                          needToIncludeAllColumns = true;
                          break;
View Full Code Here

    //columns which are used through REFERENCING clause
    GenericDescriptorList tdl = dd.getTriggerDescriptors(td);
    Enumeration descs = tdl.elements();
    while (descs.hasMoreElements())
    {
      TriggerDescriptor trd = (TriggerDescriptor) descs.nextElement();
      //If we find that the trigger is dependent on the column being
      //dropped because column is part of trigger columns list, then
      //we will give a warning or drop the trigger based on whether
      //ALTER TABLE DROP COLUMN is RESTRICT or CASCADE. In such a
      //case, no need to check if the trigger action columns referenced
      //through REFERENCING clause also used the column being dropped.
      boolean triggerDroppedAlready = false;

      int[] referencedCols = trd.getReferencedCols();
      if (referencedCols != null) {
        int refColLen = referencedCols.length, j;
        boolean changed = false;
        for (j = 0; j < refColLen; j++)
        {
          if (referencedCols[j] > droppedColumnPosition)
                  {
            //Trigger is not defined on the column being dropped
            //but the column position of trigger column is changing
            //because the position of the column being dropped is
            //before the the trigger column
            changed = true;
                  }
          else if (referencedCols[j] == droppedColumnPosition)
          {
            //the trigger is defined on the column being dropped
            if (cascade)
            {
                          trd.drop(lcc);
                          triggerDroppedAlready = true;
              activation.addWarning(
                StandardException.newWarning(
                                  SQLState.LANG_TRIGGER_DROPPED,
                                  trd.getName(), td.getName()));
            }
            else
            // we'd better give an error if don't drop it,
              // otherwsie there would be unexpected behaviors
              throw StandardException.newException(
                              SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                              dm.getActionString(DependencyManager.DROP_COLUMN),
                              columnName, "TRIGGER",
                              trd.getName() );
            }
            break;
          }
        }

        // The following if condition will be true if the column
        // getting dropped is not a trigger column, but one or more
        // of the trigge column's position has changed because of
        // drop column.
        if (j == refColLen && changed)
        {
          dd.dropTriggerDescriptor(trd, tc);
          for (j = 0; j < refColLen; j++)
          {
            if (referencedCols[j] > droppedColumnPosition)
              referencedCols[j]--;
          }
          dd.addDescriptor(trd, sd,
                   DataDictionary.SYSTRIGGERS_CATALOG_NUM,
                   false, tc);
        }
      }

      // If the trigger under consideration got dropped through the
      // loop above, then move to next trigger
      if (triggerDroppedAlready) continue;
     
      // Column being dropped is not one of trigger columns. Check if
      // that column is getting used inside the trigger action through
      // REFERENCING clause. This can be tracked only for triggers
      // created in 10.7 and higher releases. Derby releases prior to
      // that did not keep track of trigger action columns used
      // through the REFERENCING clause.
      int[] referencedColsInTriggerAction = trd.getReferencedColsInTriggerAction();
      if (referencedColsInTriggerAction != null) {
        int refColInTriggerActionLen = referencedColsInTriggerAction.length, j;
        boolean changedColPositionInTriggerAction = false;
        for (j = 0; j < refColInTriggerActionLen; j++)
        {
          if (referencedColsInTriggerAction[j] > droppedColumnPosition)
          {
            changedColPositionInTriggerAction = true;
          }
          else if (referencedColsInTriggerAction[j] == droppedColumnPosition)
          {
            if (cascade)
            {
                          trd.drop(lcc);
                          triggerDroppedAlready = true;
              activation.addWarning(
                StandardException.newWarning(
                                  SQLState.LANG_TRIGGER_DROPPED,
                                  trd.getName(), td.getName()));
            }
            else
            // we'd better give an error if don't drop it,
              throw StandardException.newException(
                              SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                              dm.getActionString(DependencyManager.DROP_COLUMN),
                              columnName, "TRIGGER",
                              trd.getName() );
            }
            break;
          }
        }

        // change trigger to refer to columns in new positions
        // The following if condition will be true if the column
        // getting dropped is not getting used in the trigger action
        // sql through the REFERENCING clause but one or more of those
        // column's position has changed because of drop column.
        // This applies only to triggers created with 10.7 and higher.
        // Prior to that, Derby did not keep track of the trigger
        // action column used through the REFERENCING clause. Such
        // triggers will be caught later on in this method after the
        // column has been actually dropped from the table descriptor.
        if (j == refColInTriggerActionLen && changedColPositionInTriggerAction)
        {
          dd.dropTriggerDescriptor(trd, tc);
          for (j = 0; j < refColInTriggerActionLen; j++)
          {
            if (referencedColsInTriggerAction[j] > droppedColumnPosition)
              referencedColsInTriggerAction[j]--;
          }
          dd.addDescriptor(trd, sd,
               DataDictionary.SYSTRIGGERS_CATALOG_NUM,
               false, tc);
        }
      }
    }

    ConstraintDescriptorList csdl = dd.getConstraintDescriptors(td);
    int csdl_size = csdl.size();

    ArrayList newCongloms = new ArrayList();

    // we want to remove referenced primary/unique keys in the second
    // round.  This will ensure that self-referential constraints will
    // work OK.
    int tbr_size = 0;
    ConstraintDescriptor[] toBeRemoved =
            new ConstraintDescriptor[csdl_size];

    // let's go downwards, don't want to get messed up while removing
    for (int i = csdl_size - 1; i >= 0; i--)
    {
      ConstraintDescriptor cd = csdl.elementAt(i);
      int[] referencedColumns = cd.getReferencedColumns();
      int numRefCols = referencedColumns.length, j;
      boolean changed = false;
      for (j = 0; j < numRefCols; j++)
      {
        if (referencedColumns[j] > droppedColumnPosition)
          changed = true;
        if (referencedColumns[j] == droppedColumnPosition)
          break;
      }
      if (j == numRefCols)      // column not referenced
      {
        if ((cd instanceof CheckConstraintDescriptor) && changed)
        {
          dd.dropConstraintDescriptor(cd, tc);
          for (j = 0; j < numRefCols; j++)
          {
            if (referencedColumns[j] > droppedColumnPosition)
              referencedColumns[j]--;
          }
          ((CheckConstraintDescriptor) cd).setReferencedColumnsDescriptor(new ReferencedColumnsDescriptorImpl(referencedColumns));
          dd.addConstraintDescriptor(cd, tc);
        }
        continue;
      }

      if (! cascade)
      {
        // Reject the DROP COLUMN, because there exists a constraint
        // which references this column.
        //
        throw StandardException.newException(
                        SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                        dm.getActionString(DependencyManager.DROP_COLUMN),
                        columnName, "CONSTRAINT",
                        cd.getConstraintName() );
      }

      if (cd instanceof ReferencedKeyConstraintDescriptor)
      {
        // restrict will raise an error in invalidate if referenced
        toBeRemoved[tbr_size++] = cd;
        continue;
      }

      // drop now in all other cases
      dm.invalidateFor(cd, DependencyManager.DROP_CONSTRAINT,
                  lcc);

      dropConstraint(cd, td, newCongloms, activation, lcc, true);
      activation.addWarning(
                StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
        cd.getConstraintName(), td.getName()));
    }

    for (int i = tbr_size - 1; i >= 0; i--)
    {
      ConstraintDescriptor cd = toBeRemoved[i];
      dropConstraint(cd, td, newCongloms, activation, lcc, false);

      activation.addWarning(
                StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
                cd.getConstraintName(), td.getName()));

      if (cascade)
      {
        ConstraintDescriptorList fkcdl = dd.getForeignKeys(cd.getUUID());
        for (int j = 0; j < fkcdl.size(); j++)
        {
          ConstraintDescriptor fkcd =
                        (ConstraintDescriptor) fkcdl.elementAt(j);

          dm.invalidateFor(fkcd,
                  DependencyManager.DROP_CONSTRAINT,
                  lcc);

          dropConstraint(fkcd, td,
            newCongloms, activation, lcc, true);

          activation.addWarning(
                        StandardException.newWarning(
                            SQLState.LANG_CONSTRAINT_DROPPED,
                fkcd.getConstraintName(),
                            fkcd.getTableDescriptor().getName()));
        }
      }

      dm.invalidateFor(cd, DependencyManager.DROP_CONSTRAINT, lcc);
      dm.clearDependencies(lcc, cd);
    }

    /* If there are new backing conglomerates which must be
     * created to replace a dropped shared conglomerate
     * (where the shared conglomerate was dropped as part
     * of a "drop constraint" call above), then create them
     * now.  We do this *after* dropping all dependent
     * constraints because we don't want to waste time
     * creating a new conglomerate if it's just going to be
     * dropped again as part of another "drop constraint".
     */
    createNewBackingCongloms(newCongloms, (long[])null);

        /*
         * The work we've done above, specifically the possible
         * dropping of primary key, foreign key, and unique constraints
         * and their underlying indexes, may have affected the table
         * descriptor. By re-reading the table descriptor here, we
         * ensure that the compressTable code is working with an
         * accurate table descriptor. Without this line, we may get
         * conglomerate-not-found errors and the like due to our
         * stale table descriptor.
         */
    td = dd.getTableDescriptor(tableId);

        compressTable();

    ColumnDescriptorList tab_cdl = td.getColumnDescriptorList();

    // drop the column from syscolumns
    dd.dropColumnDescriptor(td.getUUID(), columnName, tc);   
    ColumnDescriptor[] cdlArray =
            new ColumnDescriptor[size - columnDescriptor.getPosition()];

    // For each column in this table with a higher column position,
    // drop the entry from SYSCOLUMNS, but hold on to the column
    // descriptor and reset its position to adjust for the dropped
    // column. Then, re-add all those adjusted column descriptors
    // back to SYSCOLUMNS
    //
    for (int i = columnDescriptor.getPosition(), j = 0; i < size; i++, j++)
    {
      ColumnDescriptor cd = (ColumnDescriptor) tab_cdl.elementAt(i);
      dd.dropColumnDescriptor(td.getUUID(), cd.getColumnName(), tc);
      cd.setPosition(i);
      if (cd.isAutoincrement())
      {
        cd.setAutoinc_create_or_modify_Start_Increment(
            ColumnDefinitionNode.CREATE_AUTOINCREMENT);
      }

      cdlArray[j] = cd;
    }
    dd.addDescriptorArray(cdlArray, td,
                DataDictionary.SYSCOLUMNS_CATALOG_NUM, false, tc);

    // By this time, the column has been removed from the table descriptor.
    // Now, go through all the triggers and regenerate their trigger action
    // SPS and rebind the generated trigger action sql. If the trigger 
    // action is using the dropped column, it will get detected here. If
    // not, then we will have generated the internal trigger action sql
    // which matches the trigger action sql provided by the user.
    //
    // eg of positive test case
    // create table atdc_16_tab1 (a1 integer, b1 integer, c1 integer);
    // create table atdc_16_tab2 (a2 integer, b2 integer, c2 integer);
    // create trigger atdc_16_trigger_1
    //    after update of b1 on atdc_16_tab1
    //    REFERENCING NEW AS newt
    //    for each row
    //    update atdc_16_tab2 set c2 = newt.c1
    // The internal representation for the trigger action before the column
    // is dropped is as follows
    //    update atdc_16_tab2 set c2 =
    //   org.apache.derby.iapi.db.Factory::getTriggerExecutionContext().
    //   getONewRow().getInt(3)
    // After the drop column shown as below
    //   alter table DERBY4998_SOFT_UPGRADE_RESTRICT drop column c11
    // The above internal representation of tigger action sql is not
    // correct anymore because column position of c1 in atdc_16_tab1 has
    // now changed from 3 to 2. Following while loop will regenerate it and
    // change it to as follows
    //    update atdc_16_tab2 set c2 =
    //   org.apache.derby.iapi.db.Factory::getTriggerExecutionContext().
    //   getONewRow().getInt(2)
    //
    // We could not do this before the actual column drop, because the
    // rebind would have still found the column being dropped in the
    // table descriptor and hence use of such a column in the trigger
    // action rebind would not have been caught.

    //For the table on which ALTER TABLE is getting performed, find out
    // all the SPSDescriptors that use that table as a provider. We are
    // looking for SPSDescriptors that have been created internally for
    // trigger action SPSes. Through those SPSDescriptors, we will be
    // able to get to the triggers dependent on the table being altered
    //Following will get all the dependent objects that are using
    // ALTER TABLE table as provider
    List depsOnAlterTableList = dd.getProvidersDescriptorList(td.getObjectID().toString());
    for (Iterator depsOnAlterTableIterator = depsOnAlterTableList.listIterator();
      depsOnAlterTableIterator.hasNext();)
    {
      //Go through all the dependent objects on the table being altered
      DependencyDescriptor depOnAlterTableDesc =
        (DependencyDescriptor) depsOnAlterTableIterator.next();
      DependableFinder dependent = depOnAlterTableDesc.getDependentFinder();
      //For the given dependent, we are only interested in it if it is a
      // stored prepared statement.
      if (dependent.getSQLObjectType().equals(Dependable.STORED_PREPARED_STATEMENT))
      {
        //Look for all the dependent objects that are using this
        // stored prepared statement as provider. We are only
        // interested in dependents that are triggers.
        List depsTrigger = dd.getProvidersDescriptorList(depOnAlterTableDesc.getUUID().toString());
        for (Iterator depsTriggerIterator = depsTrigger.listIterator();
          depsTriggerIterator.hasNext();)
        {
          DependencyDescriptor depsTriggerDesc =
            (DependencyDescriptor) depsTriggerIterator.next();
          DependableFinder providerIsTrigger = depsTriggerDesc.getDependentFinder();
          //For the given dependent, we are only interested in it if
          // it is a trigger
          if (providerIsTrigger.getSQLObjectType().equals(Dependable.TRIGGER)) {
            //Drop and recreate the trigger after regenerating
            // it's trigger action plan. If the trigger action
            // depends on the column being dropped, it will be
            // caught here.
            TriggerDescriptor trdToBeDropped  = dd.getTriggerDescriptor(depsTriggerDesc.getUUID());
            columnDroppedAndTriggerDependencies(trdToBeDropped,
                cascade, columnName);
          }
        }
      }
View Full Code Here

    //truncate is not allowed when there are enabled DELETE triggers
    GenericDescriptorList tdl = dd.getTriggerDescriptors(td);
    Enumeration descs = tdl.elements();
    while (descs.hasMoreElements())
    {
      TriggerDescriptor trd = (TriggerDescriptor) descs.nextElement();
      if (trd.listensForEvent(TriggerDescriptor.TRIGGER_EVENT_DELETE) &&
        trd.isEnabled())
      {
        throw
          StandardException.newException(SQLState.LANG_NO_TRUNCATE_ON_ENABLED_DELETE_TRIGGERS,
                           td.getName(),trd.getName())
      }
    }

    //gather information from the existing conglomerate to create new one.
    emptyHeapRow = td.getEmptyExecRow();
View Full Code Here

    throws StandardException
  {
    CompilerContext       compilerContext = getCompilerContext();

        for (Iterator descIter = tdl.iterator(); descIter.hasNext() ; ) {
            TriggerDescriptor td = (TriggerDescriptor)descIter.next();
            /*
            ** The dependent now depends on this trigger.
            ** The default dependent is the statement being compiled.
            */
            if (dependent == null) {
View Full Code Here

        ** For now, we don't allow bulk insert replace when
        ** there is a trigger.
        */
        if (triggerInfo != null)
        {
          TriggerDescriptor td = triggerInfo.getTriggerArray()[0];
          throw StandardException.newException(SQLState.LANG_NO_BULK_INSERT_REPLACE_WITH_TRIGGER_DURING_EXECUTION, constants.getTableName(), td.getName());
        }
      }
    }

    //System.out.println("new InsertResultSet " + sourceResultSet.getClass());
View Full Code Here

TOP

Related Classes of org.apache.derby.iapi.sql.dictionary.TriggerDescriptor

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.