/**
   * Drops the index with the specified name from this database.
   *
   * @param indexname the name of the index to drop
   * @param ifExists if true and if the Index to drop does not exist, fail silently, else throw
   * @param session the execution context
   * @throws HsqlException if the index does not exist, the session lacks the permission or the
   *     operation violates database integrity
   */
  void dropIndex(Session session, String indexname, String tableName, boolean ifExists)
      throws HsqlException {

    Table t = findUserTableForIndex(session, indexname);

    if (t == null) {
      if (ifExists) {
        return;
      } else {
        throw Trace.error(Trace.INDEX_NOT_FOUND, indexname);
      }
    }

    if (tableName != null && !t.getName().name.equals(tableName)) {
      throw Trace.error(Trace.INDEX_NOT_FOUND, indexname);
    }

    t.checkDropIndex(indexname, null);

    // fredt@users 20020405 - patch 1.7.0 by fredt - drop index bug
    // see Table.moveDefinition();
    session.commit();
    session.setScripting(!t.isTemp());

    TableWorks tw = new TableWorks(session, t);

    tw.dropIndex(indexname);
  }
  /** Drops a trigger with the specified name in the given context. */
  void dropTrigger(Session session, String name) throws HsqlException {

    boolean found = triggerNameList.containsName(name);

    Trace.check(found, Trace.TRIGGER_NOT_FOUND, name);

    HsqlName tableName = (HsqlName) triggerNameList.removeName(name);
    Table t = this.findUserTable(session, tableName.name);

    t.dropTrigger(name);
    session.setScripting(!t.isTemp());
  }
  /**
   * Drops the specified user-defined view or table from this Database object.
   *
   * <p>The process of dropping a table or view includes:
   *
   * <OL>
   *   <LI>checking that the specified Session's currently connected User has the right to perform
   *       this operation and refusing to proceed if not by throwing.
   *   <LI>checking for referential constraints that conflict with this operation and refusing to
   *       proceed if they exist by throwing.
   *   <LI>removing the specified Table from this Database object.
   *   <LI>removing any exported foreign keys Constraint objects held by any tables referenced by
   *       the table to be dropped. This is especially important so that the dropped Table ceases to
   *       be referenced, eventually allowing its full garbage collection.
   *   <LI>
   * </OL>
   *
   * <p>
   *
   * @param name of the table or view to drop
   * @param ifExists if true and if the Table to drop does not exist, fail silently, else throw
   * @param isView true if the name argument refers to a View
   * @param session the connected context in which to perform this operation
   * @throws HsqlException if any of the checks listed above fail
   */
  void dropTable(Session session, String name, boolean ifExists, boolean isView)
      throws HsqlException {

    Table toDrop = null;
    int dropIndex = -1;

    for (int i = 0; i < tTable.size(); i++) {
      toDrop = (Table) tTable.get(i);

      if (toDrop.equals(session, name) && isView == toDrop.isView()) {
        dropIndex = i;

        break;
      } else {
        toDrop = null;
      }
    }

    if (dropIndex == -1) {
      if (ifExists) {
        return;
      } else {
        throw Trace.error(isView ? Trace.VIEW_NOT_FOUND : Trace.TABLE_NOT_FOUND, name);
      }
    }

    if (!toDrop.isTemp()) {
      session.checkDDLWrite();
    }

    if (isView) {
      checkViewIsInView((View) toDrop);
    } else {
      checkTableIsReferenced(toDrop);
      checkTableIsInView(toDrop.tableName.name);
    }

    tTable.remove(dropIndex);
    removeExportedKeys(toDrop);
    userManager.removeDbObject(toDrop.getName());
    triggerNameList.removeOwner(toDrop.tableName);
    indexNameList.removeOwner(toDrop.tableName);
    constraintNameList.removeOwner(toDrop.tableName);
    toDrop.dropTriggers();
    toDrop.drop();
    session.setScripting(!toDrop.isTemp());
    session.commit();
  }
  /**
   * Drops the index with the specified name from this database.
   *
   * @param indexname the name of the index to drop
   * @param session the execution context
   * @throws SQLException if the index does not exist, the session lacks the permission or the
   *     operation violates database integrity
   */
  void dropIndex(String indexname, Session session) throws SQLException {

    Table t = findUserTableForIndex(indexname, session);

    if (t == null) {
      throw Trace.error(Trace.INDEX_NOT_FOUND, indexname);
    }

    t.checkDropIndex(indexname, null);

    // fredt@users 20020405 - patch 1.7.0 by fredt - drop index bug
    // see Table.moveDefinition();
    session.commit();
    session.setScripting(!t.isTemp());

    TableWorks tw = new TableWorks(t);

    tw.dropIndex(indexname);
  }
  /**
   * Drops a trigger with the specified name from this Database
   *
   * @param name of the trigger to drop
   * @param session execution context
   * @throws SQLException if a database access error occurs
   */
  void dropTrigger(String name, Session session) throws SQLException {

    boolean found = false;

    // look in each trigger list of each type of trigger for each table
    for (int i = 0, tsize = tTable.size(); i < tsize; i++) {
      Table t = (Table) tTable.get(i);
      int numTrigs = TriggerDef.numTrigs();

      for (int tv = 0; tv < numTrigs; tv++) {
        HsqlArrayList v = t.vTrigs[tv];

        for (int tr = v.size() - 1; tr >= 0; tr--) {
          TriggerDef td = (TriggerDef) v.get(tr);

          if (td.name.equals(name)) {

            // fredt@users 20020221 - patch 513005 by sqlbob@users (RMP)
            session.setScripting(!td.table.isTemp());
            v.remove(tr);

            found = true;

            if (Trace.TRACE) {
              Trace.trace("Trigger dropped " + name);
            }
          }
        }
      }
    }

    Trace.check(found, Trace.TRIGGER_NOT_FOUND, name);

    // boucherb@users 20021128 - enforce unique trigger names
    triggerNameList.removeName(name);

    // ---
  }
  /**
   * Drops the specified user-defined view or table from this Database object.
   *
   * <p>The process of dropping a table or view includes:
   *
   * <OL>
   *   <LI>checking that the specified Session's currently connected User has the right to perform
   *       this operation and refusing to proceed if not by throwing.
   *   <LI>checking for referential constraints that conflict with this operation and refusing to
   *       proceed if they exist by throwing.
   *   <LI>removing the specified Table from this Database object.
   *   <LI>removing any exported foreign keys Constraint objects held by any tables referenced by
   *       the table to be dropped. This is especially important so that the dropped Table ceases to
   *       be referenced, eventually allowing its full garbage collection.
   *   <LI>
   * </OL>
   *
   * <p>
   *
   * @param name of the table or view to drop
   * @param ifExists if true and if the Table to drop does not exist, fail silently, else throw
   * @param isView true if the name argument refers to a View
   * @param session the connected context in which to perform this operation
   * @throws SQLException if any of the checks listed above fail
   */
  void dropTable(String name, boolean ifExists, boolean isView, Session session)
      throws SQLException {

    Table toDrop = null;
    int dropIndex = -1;
    int refererIndex = -1;
    Enumeration constraints = null;
    Constraint currentConstraint = null;
    Table refTable = null;
    boolean isRef = false;
    boolean isSelfRef = false;

    for (int i = 0; i < tTable.size(); i++) {
      toDrop = (Table) tTable.get(i);

      if (toDrop.equals(name, session) && isView == toDrop.isView()) {
        dropIndex = i;

        break;
      } else {
        toDrop = null;
      }
    }

    if (dropIndex == -1) {
      if (ifExists) {
        return;
      } else {
        throw Trace.error(isView ? Trace.VIEW_NOT_FOUND : Trace.TABLE_NOT_FOUND, name);
      }
    }

    constraints = toDrop.getConstraints().elements();

    while (constraints.hasMoreElements()) {
      currentConstraint = (Constraint) constraints.nextElement();

      if (currentConstraint.getType() != Constraint.MAIN) {
        continue;
      }

      refTable = currentConstraint.getRef();
      isRef = (refTable != null);
      isSelfRef = (isRef && toDrop.equals(refTable));

      if (isRef && !isSelfRef) {

        // cover the case where the referencing table
        // may have already been dropped
        for (int k = 0; k < tTable.size(); k++) {
          if (refTable.equals(tTable.get(k))) {
            refererIndex = k;

            break;
          }
        }

        if (refererIndex != -1) {

          // tony_lai@users 20020820 - patch 595156
          throw Trace.error(
              Trace.INTEGRITY_CONSTRAINT_VIOLATION,
              currentConstraint.getName().name + " table: " + refTable.getName().name);
        }
      }
    }

    tTable.remove(dropIndex);
    removeExportedKeys(toDrop);
    aAccess.removeDbObject(toDrop.getName());
    triggerNameList.removeOwner(toDrop.tableName);
    indexNameList.removeOwner(toDrop.tableName);
    toDrop.drop();
    session.setScripting(!toDrop.isTemp());
    session.commit();
  }