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

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


      {
        /* Now we have a lot of painful work to get the
         * table name for the error message.  All we have
         * is the conglomerate number to work with.
         */
        DataDictionary dd = activation.getLanguageConnectionContext().getDataDictionary();
        ConglomerateDescriptor cd = dd.getConglomerateDescriptor( heapConglom );
        TableDescriptor td = dd.getTableDescriptor(cd.getTableID());

        StandardException se = StandardException.newException(SQLState.LANG_CHECK_CONSTRAINT_VIOLATED,
          td.getQualifiedName(), checkName);

        throw se;
View Full Code Here


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

    int              numRows = 0;
        boolean            tableScanned = false;

    /*
    ** 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);

    // now do the real work

    // get an exclusive lock of the heap, to avoid deadlock on rows of
    // SYSCOLUMNS etc datadictionary tables and phantom table
    // descriptor, in which case table shape could be changed by a
    // concurrent thread doing add/drop column.

    // older version (or at target) has to get td first, potential deadlock
    if (tableConglomerateId == 0)
    {
      td = dd.getTableDescriptor(tableId);
      if (td == null)
      {
        throw StandardException.newException(
          SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);
      }
      tableConglomerateId = td.getHeapConglomerateId();
    }

    lockTableForDDL(tc, tableConglomerateId, true);

    td = dd.getTableDescriptor(tableId);
    if (td == null)
    {
      throw StandardException.newException(
        SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);
    }

    if (truncateTable)
      dm.invalidateFor(td, DependencyManager.TRUNCATE_TABLE, lcc);
    else
      dm.invalidateFor(td, DependencyManager.ALTER_TABLE, lcc);

    // Save the TableDescriptor off in the Activation
    activation.setDDLTableDescriptor(td);

    /*
    ** If the schema descriptor is null, then we must have just read
        ** ourselves in.  So we will get the corresponding schema descriptor
        ** from the data dictionary.
    */
    if (sd == null)
    {
      sd = getAndCheckSchemaDescriptor(dd, schemaId, "ALTER TABLE");
    }
   
    /* Prepare all dependents to invalidate.  (This is there chance
     * to say that they can't be invalidated.  For example, an open
     * cursor referencing a table/view that the user is attempting to
     * alter.) If no one objects, then invalidate any dependent objects.
     */
    if(truncateTable)
      dm.invalidateFor(td, DependencyManager.TRUNCATE_TABLE, lcc);
    else
      dm.invalidateFor(td, DependencyManager.ALTER_TABLE, lcc);

    // Are we working on columns?
    if (columnInfo != null)
    {
            boolean tableNeedsScanning = false;

      /* NOTE: We only allow a single column to be added within
       * each ALTER TABLE command at the language level.  However,
       * this may change some day, so we will try to plan for it.
       */
      /* for each new column, see if the user is adding a non-nullable
       * column.  This is only allowed on an empty table.
       */
      for (int ix = 0; ix < columnInfo.length; ix++)
      {

        /* Is this new column non-nullable? 
         * If so, it can only be added to an
         * empty table if it does not have a default value. 
         * We need to scan the table to find out how many rows
         * there are.
         */
        if ((columnInfo[ix].action == ColumnInfo.CREATE) &&
          !(columnInfo[ix].dataType.isNullable()) &&
          (columnInfo[ix].defaultInfo == null) &&
          (columnInfo[ix].autoincInc == 0)
          )
        {
          tableNeedsScanning = true;
        }
      }

      // Scan the table if necessary
      if (tableNeedsScanning)
      {
        numRows = getSemiRowCount(tc);
        // Don't allow add of non-nullable column to non-empty table
        if (numRows > 0)
        {
          throw StandardException.newException(
                        SQLState.LANG_ADDING_NON_NULL_COLUMN_TO_NON_EMPTY_TABLE,
                        td.getQualifiedName());
        }
        tableScanned = true;
      }

      // for each related column, stuff system.column
      for (int ix = 0; ix < columnInfo.length; ix++)
      {
        ColumnDescriptorList cdl = new ColumnDescriptorList();

        /* If there is a default value, use it, otherwise use null */
       
        // Are we adding a new column or modifying a default?
       
        if (columnInfo[ix].action == ColumnInfo.CREATE)
        {
          addNewColumnToTable(activation, lcc, dd, tc, ix);
        }
        else if (columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_DEFAULT_RESTART ||
             columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_DEFAULT_INCREMENT ||
             columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_DEFAULT_VALUE)
        {
          modifyColumnDefault(activation, ix);
        }
        else if (columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_TYPE)
        {
          modifyColumnType(activation, ix);
        }
        else if (columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_CONSTRAINT)
        {
          modifyColumnConstraint(
                        activation, columnInfo[ix].name, true);
        }
        else if (columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_CONSTRAINT_NOT_NULL)
        {
          if (!tableScanned)
          {
            tableScanned = true;
            numRows = getSemiRowCount(tc);
          }

          // check that the data in the column is not null
          String colNames[]  = new String[1];
          colNames[0]        = columnInfo[ix].name;
          boolean nullCols[] = new boolean[1];

          /* note validateNotNullConstraint returns true if the
           * column is nullable
           */
          if (validateNotNullConstraint(
                            colNames, nullCols, numRows, lcc,
                            SQLState.LANG_NULL_DATA_IN_NON_NULL_COLUMN))
          {
            /* nullable column - modify it to be not null
             * This is O.K. at this point since we would have
             * thrown an exception if any data was null
             */
            modifyColumnConstraint(
                            activation, columnInfo[ix].name, false);
          }
        }
        else if (columnInfo[ix].action == ColumnInfo.DROP)
        {
          dropColumnFromTable(activation, ix);
        }
        else if (SanityManager.DEBUG)
        {
          SanityManager.THROWASSERT(
                "Unexpected action in AlterTableConstantAction");
        }
      }
    }

    /* Create/Drop any constraints */
    if (constraintActions != null)
    {
      for (int conIndex = 0;
                 conIndex < constraintActions.length;
                 conIndex++)
      {
        ConstraintConstantAction cca = constraintActions[conIndex];

        if (cca instanceof CreateConstraintConstantAction)
        {
          int constraintType = cca.getConstraintType();

          /* Some constraint types require special checking:
           *   Check     - table must be empty, for now
           *   Primary Key - table cannot already have a primary key
           */
          switch (constraintType)
          {
            case DataDictionary.PRIMARYKEY_CONSTRAINT:

              // Check to see if a constraint of the same type
                            // already exists
              ConstraintDescriptorList cdl =
                                dd.getConstraintDescriptors(td);

              if (cdl.getPrimaryKey() != null)
              {
                throw StandardException.newException(
                                    SQLState.LANG_ADD_PRIMARY_KEY_FAILED1,
                                    td.getQualifiedName());
              }

              if (!tableScanned)
              {
                tableScanned = true;
                numRows = getSemiRowCount(tc);
              }

              break;

            case DataDictionary.CHECK_CONSTRAINT:

              if (!tableScanned)
              {
                tableScanned = true;
                numRows = getSemiRowCount(tc);
              }
              if (numRows > 0)
              {
                /*
                ** We are assuming that there will only be one
                ** check constraint that we are adding, so it
                ** is ok to do the check now rather than try
                ** to lump together several checks. 
                */
                ConstraintConstantAction.validateConstraint(
                                    cca.getConstraintName(),
                                    ((CreateConstraintConstantAction)cca).getConstraintText(),
                                    td,
                                    lcc, true);
              }
              break;
          }
        }
        else
        {
          if (SanityManager.DEBUG)
          {
            if (!(cca instanceof DropConstraintConstantAction))
            {
              SanityManager.THROWASSERT(
                                "constraintActions[" + conIndex +
                                "] expected to be instanceof " +
                                "DropConstraintConstantAction not " +
                                cca.getClass().getName());
            }
          }
        }

        constraintActions[conIndex].executeConstantAction(activation);
      }
    }

    // Are we changing the lock granularity?
    if (lockGranularity != '\0')
    {
      if (SanityManager.DEBUG)
      {
        if (lockGranularity != 'T' &&
          lockGranularity != 'R')
        {
          SanityManager.THROWASSERT(
            "lockGranularity expected to be 'T'or 'R', not " +
                        lockGranularity);
        }
      }

      // update the TableDescriptor
      td.setLockGranularity(lockGranularity);
      // update the DataDictionary
      dd.updateLockGranularity(td, sd, lockGranularity, tc);
    }

    // Are we doing a compress table?
    if (compressTable)
    {
View Full Code Here

  private void dropColumnFromTable(Activation activation,
                   int ix)
          throws StandardException
  {
    LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
    DataDictionary dd = lcc.getDataDictionary();
    DependencyManager dm = dd.getDependencyManager();
    TransactionController tc = lcc.getTransactionExecute();


    ColumnDescriptor columnDescriptor =
      td.getColumnDescriptor(columnInfo[ix].name);

    // We already verified this in bind, but do it again
    if (columnDescriptor == null)
    {
      throw
        StandardException.newException(
                    SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE,
                    columnInfo[ix].name,
                    td.getQualifiedName());
    }

    DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
    ColumnDescriptorList tab_cdl = td.getColumnDescriptorList();
    int size = tab_cdl.size();

    // can NOT drop a column if it is the only one in the table
    if (size == 1)
    {
      throw StandardException.newException(
                    SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                    dm.getActionString(DependencyManager.DROP_COLUMN),
                    "THE *LAST* COLUMN " + columnInfo[ix].name,
                    "TABLE",
                    td.getQualifiedName() );
    }

    droppedColumnPosition = columnDescriptor.getPosition();
    boolean cascade = (behavior == StatementType.DROP_CASCADE);

    FormatableBitSet toDrop = new FormatableBitSet(size + 1);
    toDrop.set(droppedColumnPosition);
    td.setReferencedColumnMap(toDrop);

    dm.invalidateFor(td,
                        (cascade ? DependencyManager.DROP_COLUMN
                                 : DependencyManager.DROP_COLUMN_RESTRICT),
                        lcc);
         
    // If column has a default we drop the default and any dependencies
    if (columnDescriptor.getDefaultInfo() != null)
    {
      dm.clearDependencies(
                lcc, columnDescriptor.getDefaultDescriptor(dd));
    }

    // need to deal with triggers if has referencedColumns
    GenericDescriptorList tdl = dd.getTriggerDescriptors(td);
    Enumeration descs = tdl.elements();
    while (descs.hasMoreElements())
    {
      TriggerDescriptor trd = (TriggerDescriptor) descs.nextElement();
      int[] referencedCols = trd.getReferencedCols();
      if (referencedCols == null)
        continue;
      int refColLen = referencedCols.length, j;
      boolean changed = false;
      for (j = 0; j < refColLen; j++)
      {
        if (referencedCols[j] > droppedColumnPosition)
                {
          changed = true;
                }
        else if (referencedCols[j] == droppedColumnPosition)
        {
          if (cascade)
          {
                        trd.drop(lcc);
            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),
                            columnInfo[ix].name, "TRIGGER",
                            trd.getName() );
          }
          break;
        }
      }

      // change triggers to refer to columns in new positions
      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);
      }
    }

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

    // 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),
                        columnInfo[ix].name, "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);
            cd.drop(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];
      cd.drop(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);

                    fkcd.drop(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);
    }

        /*
         * 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(activation);

    // drop the column from syscolumns
    dd.dropColumnDescriptor(td.getUUID(), columnInfo[ix].name, 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);

    List deps = dd.getProvidersDescriptorList(td.getObjectID().toString());
    for (Iterator depsIterator = deps.listIterator();
             depsIterator.hasNext();)
    {
      DependencyDescriptor depDesc =
                (DependencyDescriptor) depsIterator.next();

      DependableFinder finder = depDesc.getProviderFinder();
      if (finder instanceof DDColumnDependableFinder)
      {
        DDColumnDependableFinder colFinder =
                    (DDColumnDependableFinder) finder;
        FormatableBitSet oldColumnBitMap =
                    new FormatableBitSet(colFinder.getColumnBitMap());
        FormatableBitSet newColumnBitMap =
                    new FormatableBitSet(oldColumnBitMap);
        newColumnBitMap.clear();
        int bitLen = oldColumnBitMap.getLength();
        for (int i = 0; i < bitLen; i++)
        {
          if (i < droppedColumnPosition && oldColumnBitMap.isSet(i))
            newColumnBitMap.set(i);
          if (i > droppedColumnPosition && oldColumnBitMap.isSet(i))
            newColumnBitMap.set(i - 1);
        }
        if (newColumnBitMap.equals(oldColumnBitMap))
          continue;
        dd.dropStoredDependency(depDesc, tc);
        colFinder.setColumnBitMap(newColumnBitMap.getByteArray());
        dd.addDescriptor(depDesc, null,
                 DataDictionary.SYSDEPENDS_CATALOG_NUM,
                 true, tc);
      }
    }
    // Adjust the column permissions rows in SYSCOLPERMS to reflect the
    // changed column positions due to the dropped column:
    dd.updateSYSCOLPERMSforDropColumn(td.getUUID(), tc, columnDescriptor);
  }
View Full Code Here

  private void modifyColumnType(Activation activation,
                  int ix)
    throws StandardException             
  {
    LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
    DataDictionary dd = lcc.getDataDictionary();
    TransactionController tc = lcc.getTransactionExecute();

    ColumnDescriptor columnDescriptor =
      td.getColumnDescriptor(columnInfo[ix].name),
      newColumnDescriptor = null;

    newColumnDescriptor =
      new ColumnDescriptor(columnInfo[ix].name,
                  columnDescriptor.getPosition(),
                  columnInfo[ix].dataType,
                  columnDescriptor.getDefaultValue(),
                  columnDescriptor.getDefaultInfo(),
                  td,
                  columnDescriptor.getDefaultUUID(),
                    columnInfo[ix].autoincStart,
                    columnInfo[ix].autoincInc
                  );
   


    // Update the ColumnDescriptor with new default info
    dd.dropColumnDescriptor(td.getUUID(), columnInfo[ix].name, tc);
    dd.addDescriptor(newColumnDescriptor, td,
             DataDictionary.SYSCOLUMNS_CATALOG_NUM, false, tc);
 
View Full Code Here

    LanguageConnectionContext lcc       = ConnectionUtil.getCurrentLCC();
    TransactionController     tc        = lcc.getTransactionExecute();

    try
        {
            DataDictionary data_dictionary = lcc.getDataDictionary();
            SchemaDescriptor sd =
                data_dictionary.getSchemaDescriptor(schema, tc, true);
            TableDescriptor  td =
                data_dictionary.getTableDescriptor(tablename, sd, tc);

            if (td != null && td.getTableType() == TableDescriptor.VTI_TYPE)
            {
                return;
            }
View Full Code Here

      {
        /* Now we have a lot of painful work to get the
         * table name for the error message.  All we have
         * is the conglomerate number to work with.
         */
        DataDictionary dd = activation.getLanguageConnectionContext().getDataDictionary();
        ConglomerateDescriptor cd = dd.getConglomerateDescriptor( heapConglom );
        TableDescriptor td = dd.getTableDescriptor(cd.getTableID());

        StandardException se = StandardException.newException(SQLState.LANG_CHECK_CONSTRAINT_VIOLATED,
          td.getQualifiedName(), checkName);

        throw se;
View Full Code Here

                  List grantees)
    throws StandardException
  {
    // Check that the current user has permission to grant the privileges.
    LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
    DataDictionary dd = lcc.getDataDictionary();
    String currentUser = lcc.getAuthorizationId();
    TransactionController tc = lcc.getTransactionExecute();
        SchemaDescriptor sd = _tupleDescriptor.getSchemaDescriptor();
        UUID objectID = _tupleDescriptor.getUUID();
        String objectTypeName = _tupleDescriptor.getObjectTypeName();

    // Check that the current user has permission to grant the privileges.
    checkOwnership( currentUser, (TupleDescriptor) _tupleDescriptor, sd, dd );
   
    DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();

    PermDescriptor permDesc = ddg.newPermDescriptor
            ( null, objectTypeName, objectID, _privilege, currentUser, null, false );

    dd.startWriting(lcc);
    for( Iterator itr = grantees.iterator(); itr.hasNext();)
    {
      // Keep track to see if any privileges are revoked by a revoke
      // statement. If a privilege is not revoked, we need to raise a
      // warning.
      boolean privileges_revoked = false;
      String grantee = (String) itr.next();
      if (dd.addRemovePermissionsDescriptor( grant, permDesc, grantee, tc))
      {
                //
                // We fall in here if we are performing REVOKE.
                //
        privileges_revoked = true
                int invalidationType = _restrict ? DependencyManager.REVOKE_PRIVILEGE_RESTRICT : DependencyManager.REVOKE_PRIVILEGE;

        dd.getDependencyManager().invalidateFor( permDesc, invalidationType, lcc );

        // Now invalidate all GPSs refering to the object.
        dd.getDependencyManager().invalidateFor(_tupleDescriptor, invalidationType, lcc );
      }
     
      addWarningIfPrivilegeNotRevoked(activation, grant, privileges_revoked, grantee);
    }
  } // end of executeGrantRevoke
View Full Code Here

   * @exception StandardException    Thrown on error
   */
  void verifyTargetTable()
    throws StandardException
  {
                DataDictionary dataDictionary = getDataDictionary();
    if (targetTableName != null)
    {
      /*
      ** Get the TableDescriptor for the table we are inserting into
      */
 
View Full Code Here

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

    int              numRows = 0;
        boolean            tableScanned = false;

        //Following if is for inplace compress. Compress using temporary
        //tables to do the compression is done later in this method.
    if (compressTable)
    {
      if (purge || defragment || truncateEndOfTable)
      {
        td = dd.getTableDescriptor(tableId);
        if (td == null)
        {
          throw StandardException.newException(
            SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);
        }
              // Each of the following may give up locks allowing ddl on the
              // table, so each phase needs to do the data dictionary lookup.
              // The order is important as it makes sense to first purge
              // deleted rows, then defragment existing non-deleted rows, and
              // finally to truncate the end of the file which may have been
              // made larger by the previous purge/defragment pass.
              if (purge)
                  purgeRows(tc);

              if (defragment)
                  defragmentRows(tc, lcc);

              if (truncateEndOfTable)
                  truncateEnd(tc);           
              return;       
      }
    }

    if (updateStatistics)
    {
      updateStatistics(activation);
            return;
    }
    /*
    ** 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);

    // now do the real work

    // get an exclusive lock of the heap, to avoid deadlock on rows of
    // SYSCOLUMNS etc datadictionary tables and phantom table
    // descriptor, in which case table shape could be changed by a
    // concurrent thread doing add/drop column.

    // older version (or at target) has to get td first, potential deadlock
    if (tableConglomerateId == 0)
    {
      td = dd.getTableDescriptor(tableId);
      if (td == null)
      {
        throw StandardException.newException(
          SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);
      }
      tableConglomerateId = td.getHeapConglomerateId();
    }

    lockTableForDDL(tc, tableConglomerateId, true);

    td = dd.getTableDescriptor(tableId);
    if (td == null)
    {
      throw StandardException.newException(
        SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);
    }

    if (truncateTable)
      dm.invalidateFor(td, DependencyManager.TRUNCATE_TABLE, lcc);
    else
      dm.invalidateFor(td, DependencyManager.ALTER_TABLE, lcc);

    // Save the TableDescriptor off in the Activation
    activation.setDDLTableDescriptor(td);

    /*
    ** If the schema descriptor is null, then we must have just read
        ** ourselves in.  So we will get the corresponding schema descriptor
        ** from the data dictionary.
    */
    if (sd == null)
    {
      sd = getAndCheckSchemaDescriptor(dd, schemaId, "ALTER TABLE");
    }
   
    /* Prepare all dependents to invalidate.  (This is there chance
     * to say that they can't be invalidated.  For example, an open
     * cursor referencing a table/view that the user is attempting to
     * alter.) If no one objects, then invalidate any dependent objects.
     */
    if(truncateTable)
      dm.invalidateFor(td, DependencyManager.TRUNCATE_TABLE, lcc);
    else
      dm.invalidateFor(td, DependencyManager.ALTER_TABLE, lcc);

    // Are we working on columns?
    if (columnInfo != null)
    {
            boolean tableNeedsScanning = false;

      /* NOTE: We only allow a single column to be added within
       * each ALTER TABLE command at the language level.  However,
       * this may change some day, so we will try to plan for it.
       */
      /* for each new column, see if the user is adding a non-nullable
       * column.  This is only allowed on an empty table.
       */
      for (int ix = 0; ix < columnInfo.length; ix++)
      {

        /* Is this new column non-nullable? 
         * If so, it can only be added to an
         * empty table if it does not have a default value. 
         * We need to scan the table to find out how many rows
         * there are.
         */
        if ((columnInfo[ix].action == ColumnInfo.CREATE) &&
          !(columnInfo[ix].dataType.isNullable()) &&
          (columnInfo[ix].defaultInfo == null) &&
          (columnInfo[ix].autoincInc == 0)
          )
        {
          tableNeedsScanning = true;
        }
      }

      // Scan the table if necessary
      if (tableNeedsScanning)
      {
        numRows = getSemiRowCount(tc);
        // Don't allow add of non-nullable column to non-empty table
        if (numRows > 0)
        {
          throw StandardException.newException(
                        SQLState.LANG_ADDING_NON_NULL_COLUMN_TO_NON_EMPTY_TABLE,
                        td.getQualifiedName());
        }
        tableScanned = true;
      }

      // for each related column, stuff system.column
      for (int ix = 0; ix < columnInfo.length; ix++)
      {
        ColumnDescriptorList cdl = new ColumnDescriptorList();

        /* If there is a default value, use it, otherwise use null */
       
        // Are we adding a new column or modifying a default?
       
        if (columnInfo[ix].action == ColumnInfo.CREATE)
        {
          addNewColumnToTable(activation, lcc, dd, tc, ix);
        }
        else if (columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_DEFAULT_RESTART ||
             columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_DEFAULT_INCREMENT ||
             columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_DEFAULT_VALUE)
        {
          modifyColumnDefault(activation, ix);
        }
        else if (columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_TYPE)
        {
          modifyColumnType(activation, ix);
        }
        else if (columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_CONSTRAINT)
        {
          modifyColumnConstraint(
                        activation, columnInfo[ix].name, true);
        }
        else if (columnInfo[ix].action ==
             ColumnInfo.MODIFY_COLUMN_CONSTRAINT_NOT_NULL)
        {
          if (!tableScanned)
          {
            tableScanned = true;
            numRows = getSemiRowCount(tc);
          }

          // check that the data in the column is not null
          String colNames[]  = new String[1];
          colNames[0]        = columnInfo[ix].name;
          boolean nullCols[] = new boolean[1];

          /* note validateNotNullConstraint returns true if the
           * column is nullable
           */
          if (validateNotNullConstraint(
                            colNames, nullCols, numRows, lcc,
                            SQLState.LANG_NULL_DATA_IN_NON_NULL_COLUMN))
          {
            /* nullable column - modify it to be not null
             * This is O.K. at this point since we would have
             * thrown an exception if any data was null
             */
            modifyColumnConstraint(
                            activation, columnInfo[ix].name, false);
          }
        }
        else if (columnInfo[ix].action == ColumnInfo.DROP)
        {
          dropColumnFromTable(activation, columnInfo[ix].name);
        }
        else if (SanityManager.DEBUG)
        {
          SanityManager.THROWASSERT(
                "Unexpected action in AlterTableConstantAction");
        }
      }
    }

        // adjust dependencies on user defined types
        adjustUDTDependencies( lcc, dd, td, columnInfo, false );

    /* Create/Drop any constraints */
    if (constraintActions != null)
    {
      for (int conIndex = 0;
                 conIndex < constraintActions.length;
                 conIndex++)
      {
        ConstraintConstantAction cca = constraintActions[conIndex];

        if (cca instanceof CreateConstraintConstantAction)
        {
          int constraintType = cca.getConstraintType();

          /* Some constraint types require special checking:
           *   Check     - table must be empty, for now
           *   Primary Key - table cannot already have a primary key
           */
          switch (constraintType)
          {
            case DataDictionary.PRIMARYKEY_CONSTRAINT:

              // Check to see if a constraint of the same type
                            // already exists
              ConstraintDescriptorList cdl =
                                dd.getConstraintDescriptors(td);

              if (cdl.getPrimaryKey() != null)
              {
                throw StandardException.newException(
                                    SQLState.LANG_ADD_PRIMARY_KEY_FAILED1,
                                    td.getQualifiedName());
              }

              if (!tableScanned)
              {
                tableScanned = true;
                numRows = getSemiRowCount(tc);
              }

              break;

            case DataDictionary.CHECK_CONSTRAINT:

              if (!tableScanned)
              {
                tableScanned = true;
                numRows = getSemiRowCount(tc);
              }
              if (numRows > 0)
              {
                /*
                ** We are assuming that there will only be one
                ** check constraint that we are adding, so it
                ** is ok to do the check now rather than try
                ** to lump together several checks. 
                */
                ConstraintConstantAction.validateConstraint(
                                    cca.getConstraintName(),
                                    ((CreateConstraintConstantAction)cca).getConstraintText(),
                                    td,
                                    lcc, true);
              }
              break;
          }
        }
        else
        {
          if (SanityManager.DEBUG)
          {
            if (!(cca instanceof DropConstraintConstantAction))
            {
              SanityManager.THROWASSERT(
                                "constraintActions[" + conIndex +
                                "] expected to be instanceof " +
                                "DropConstraintConstantAction not " +
                                cca.getClass().getName());
            }
          }
        }

        constraintActions[conIndex].executeConstantAction(activation);
      }
    }

    // Are we changing the lock granularity?
    if (lockGranularity != '\0')
    {
      if (SanityManager.DEBUG)
      {
        if (lockGranularity != 'T' &&
          lockGranularity != 'R')
        {
          SanityManager.THROWASSERT(
            "lockGranularity expected to be 'T'or 'R', not " +
                        lockGranularity);
        }
      }

      // update the TableDescriptor
      td.setLockGranularity(lockGranularity);
      // update the DataDictionary
      dd.updateLockGranularity(td, sd, lockGranularity, tc);
    }

    // Are we doing a compress table?
    if (compressTable)
    {
View Full Code Here

   */
  private void updateStatistics(Activation activation)
  throws StandardException
  {
    LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
    DataDictionary dd = lcc.getDataDictionary();
    TransactionController tc = lcc.getTransactionExecute();
    ConglomerateDescriptor[] cds;
    long[] conglomerateNumber;
    ExecIndexRow[] indexRow;
    UUID[] objectUUID;
    GroupFetchScanController gsc;
    DependencyManager dm = dd.getDependencyManager();
    //initialize numRows to -1 so we can tell if we scanned an index. 
    long numRows = -1;   
   
    td = dd.getTableDescriptor(tableId);
    if (updateStatisticsAll)
    {
      cds = td.getConglomerateDescriptors();
    }
    else
    {
      cds = new ConglomerateDescriptor[1];
      cds[0] = dd.getConglomerateDescriptor(indexNameForUpdateStatistics, sd, false);
    }

    conglomerateNumber = new long[cds.length];
    indexRow = new ExecIndexRow[cds.length];
    objectUUID = new UUID[cds.length];
    ConglomerateController heapCC =
      tc.openConglomerate(td.getHeapConglomerateId(), false, 0,
          TransactionController.MODE_RECORD,
          TransactionController.ISOLATION_REPEATABLE_READ);

    try
    {
      for (int i = 0; i < cds.length; i++)
      {
        if (!cds[i].isIndex())
        {
          conglomerateNumber[i] = -1;
          continue;
        }

        conglomerateNumber[i] = cds[i].getConglomerateNumber();

        objectUUID[i] = cds[i].getUUID();

        indexRow[i] =
          cds[i].getIndexDescriptor().getNullIndexRow(
            td.getColumnDescriptorList(),
            heapCC.newRowLocationTemplate());
      }
    }
    finally
    {
      heapCC.close();
    }

    dd.startWriting(lcc);

    dm.invalidateFor(td, DependencyManager.UPDATE_STATISTICS, lcc);

    for (int indexNumber = 0; indexNumber < conglomerateNumber.length;
       indexNumber++)
    {
      if (conglomerateNumber[indexNumber] == -1)
        continue;

      int numCols = indexRow[indexNumber].nColumns() - 1;
      long[] cardinality = new long[numCols];
      numRows = 0;
      initializeRowBuffers(indexRow[indexNumber]);

      /* Read uncommited, with record locking. Actually CS store may
         not hold record locks */
      gsc =
        tc.openGroupFetchScan(
            conglomerateNumber[indexNumber],
            false,  // hold
            0,      // openMode: for read
            TransactionController.MODE_RECORD, // locking
            TransactionController.ISOLATION_READ_UNCOMMITTED, //isolation level
            null,   // scancolumnlist-- want everything.
            null,   // startkeyvalue-- start from the beginning.
            0,
            null,   // qualifiers, none!
            null,   // stopkeyvalue,
            0);

      try
      {
        boolean firstRow = true;
        int rowsFetched = 0;
        while ((rowsFetched = gsc.fetchNextGroup(rowBufferArray, null)) > 0)
        {
          for (int i = 0; i < rowsFetched; i++)
          {
            int whichPositionChanged = compareWithPrevKey(i, firstRow);
            firstRow = false;
            if (whichPositionChanged >= 0)
            {
              for (int j = whichPositionChanged; j < cardinality.length; j++)
                cardinality[j]++;
            }
            numRows++;
          }

          DataValueDescriptor[] tmp;
          tmp = rowBufferArray[GROUP_FETCH_SIZE - 1];
          rowBufferArray[GROUP_FETCH_SIZE - 1] = lastUniqueKey;
          lastUniqueKey = tmp;
        } // while
        gsc.setEstimatedRowCount(numRows);
      } // try
      finally
      {
        gsc.close();
        gsc = null;
      }

      if (numRows == 0)
      {
        /* if there is no data in the table: no need to write anything
         * to sys.sysstatstics
         */
        break;     
      }

      StatisticsDescriptor statDesc;

      dd.dropStatisticsDescriptors(tableId, objectUUID[indexNumber],
                     tc);

      for (int i = 0; i < indexRow[indexNumber].nColumns() - 1; i++)
      {
        statDesc = new StatisticsDescriptor(dd, dd.getUUIDFactory().createUUID(),
            objectUUID[indexNumber],
            tableId,
            "I",
            new StatisticsImpl(numRows,
                cardinality[i]),
                i + 1);
        dd.addDescriptor(statDesc, null,
            DataDictionary.SYSSTATISTICS_CATALOG_NUM,
                 true, tc);
      } // for each leading column (c1) (c1,c2)....

    } // for each index.
View Full Code Here

TOP

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

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.