/**
   * restore the before image of the page
   *
   * @exception StandardException Standard Derby Error Policy
   * @exception IOException problem reading the complete log record from the input stream
   */
  public void restoreMe(
      Transaction xact, BasePage undoPage, LogInstant CLRInstant, LimitObjectInput in)
      throws StandardException, IOException {
    int slot = undoPage.findRecordById(recordId, Page.FIRST_SLOT_NUMBER);
    if (SanityManager.DEBUG) {
      if (!getPageId().equals(undoPage.getPageId()))
        SanityManager.THROWASSERT(
            "restoreMe cannot restore to a different page. "
                + "doMe page:"
                + getPageId()
                + " undoPage:"
                + undoPage.getPageId());
      if (slot != doMeSlot)
        SanityManager.THROWASSERT(
            "restoreMe cannot restore to a different slot. "
                + "doMe slot:"
                + doMeSlot
                + " undoMe slot: "
                + slot
                + " recordId:"
                + recordId);
    }

    undoPage.skipField(in); // skip the after image of the column
    undoPage.storeField(CLRInstant, slot, fieldId, in);
    undoPage.setAuxObject(null);
  }
Exemplo n.º 2
0
  /**
   * Get a BigDecimal representing the value of a DataValueDescriptor
   *
   * @param value Non-null value to be converted
   * @return BigDecimal value
   * @throws StandardException Invalid conversion or out of range.
   */
  public static BigDecimal getBigDecimal(DataValueDescriptor value) throws StandardException {
    if (SanityManager.DEBUG) {
      if (value.isNull())
        SanityManager.THROWASSERT("NULL value passed to SQLDecimal.getBigDecimal");
    }

    switch (value.typeToBigDecimal()) {
      case Types.DECIMAL:
        return (BigDecimal) value.getObject();
      case Types.CHAR:
        try {
          return new BigDecimal(value.getString().trim());
        } catch (NumberFormatException nfe) {
          throw StandardException.newException(
              SQLState.LANG_FORMAT_EXCEPTION, "java.math.BigDecimal");
        }
      case Types.BIGINT:
        return BigDecimal.valueOf(value.getLong());
      default:
        if (SanityManager.DEBUG)
          SanityManager.THROWASSERT(
              "invalid return from "
                  + value.getClass()
                  + ".typeToBigDecimal() "
                  + value.typeToBigDecimal());
        return null;
    }
  }
  /**
   * Restore field to its old value.
   *
   * @exception IOException Can be thrown by any of the methods of ObjectInput.
   * @exception StandardException Standard Derby policy.
   * @see LogicalPageOperation#undoMe
   */
  public void undoMe(
      Transaction xact,
      BasePage undoPage,
      int undoRecordId,
      LogInstant CLRInstant,
      LimitObjectInput in)
      throws StandardException, IOException {
    int slot = undoPage.findRecordById(undoRecordId, Page.FIRST_SLOT_NUMBER);

    if (SanityManager.DEBUG) {
      // if the record Id has changed, the page had better changed
      // this can only happen during recovery since in run time undo,
      // this resetRecordHandle gets called and this object have the new
      // page number and recordId
      if (undoRecordId != this.recordId)
        if (undoPage.getPageNumber() == getPageId().getPageNumber())
          SanityManager.THROWASSERT(
              "recordId changed from "
                  + this.recordId
                  + " to "
                  + undoRecordId
                  + " but page number did not change "
                  + undoPage.getPageNumber());

      if (slot == -1)
        SanityManager.THROWASSERT(
            "recordId " + undoRecordId + " not found on page " + undoPage.getPageNumber());
    }

    undoPage.skipField((java.io.ObjectInput) in); // skip the after image of the column
    undoPage.storeField(CLRInstant, slot, fieldId, in);
    undoPage.setAuxObject(null);
  }
  String nullMethodName() {
    int formatId = getStoredFormatIdFromTypeId();
    switch (formatId) {
      case StoredFormatIds.DECIMAL_TYPE_ID:
        return "getNullDecimal";

      case StoredFormatIds.DOUBLE_TYPE_ID:
        return "getNullDouble";

      case StoredFormatIds.INT_TYPE_ID:
        return "getNullInteger";

      case StoredFormatIds.LONGINT_TYPE_ID:
        return "getNullLong";

      case StoredFormatIds.REAL_TYPE_ID:
        return "getNullFloat";

      case StoredFormatIds.SMALLINT_TYPE_ID:
        return "getNullShort";

      case StoredFormatIds.TINYINT_TYPE_ID:
        return "getNullByte";

      default:
        if (SanityManager.DEBUG) {
          SanityManager.THROWASSERT("unexpected formatId in nullMethodName() - " + formatId);
        }
        return null;
    }
  }
  /**
   * Get the method name for getting out the corresponding primitive Java type.
   *
   * @return String The method call name for getting the corresponding primitive Java type.
   */
  public String getPrimitiveMethodName() {
    int formatId = getStoredFormatIdFromTypeId();
    switch (formatId) {
      case StoredFormatIds.DOUBLE_TYPE_ID:
        return "getDouble";

      case StoredFormatIds.INT_TYPE_ID:
        return "getInt";

      case StoredFormatIds.LONGINT_TYPE_ID:
        return "getLong";

      case StoredFormatIds.REAL_TYPE_ID:
        return "getFloat";

      case StoredFormatIds.SMALLINT_TYPE_ID:
        return "getShort";

      case StoredFormatIds.TINYINT_TYPE_ID:
        return "getByte";

      case StoredFormatIds.DECIMAL_TYPE_ID:
      default:
        if (SanityManager.DEBUG) {
          SanityManager.THROWASSERT(
              "unexpected formatId in getPrimitiveMethodName() - " + formatId);
        }
        return null;
    }
  }
Exemplo n.º 6
0
 /**
  * Get the method name for getting out the corresponding primitive Java type.
  *
  * @return String The method call name for getting the corresponding primitive Java type.
  */
 public String getPrimitiveMethodName() {
   if (SanityManager.DEBUG) {
     SanityManager.THROWASSERT(
         "getPrimitiveMethodName not applicable for " + getClass().toString());
   }
   return null;
 }
  /** @see TypeCompiler#getCorrespondingPrimitiveTypeName */
  public String getCorrespondingPrimitiveTypeName() {
    /* Only numerics and booleans get mapped to Java primitives */
    int formatId = getStoredFormatIdFromTypeId();
    switch (formatId) {
      case StoredFormatIds.DOUBLE_TYPE_ID:
        return "double";

      case StoredFormatIds.INT_TYPE_ID:
        return "int";

      case StoredFormatIds.LONGINT_TYPE_ID:
        return "long";

      case StoredFormatIds.REAL_TYPE_ID:
        return "float";

      case StoredFormatIds.SMALLINT_TYPE_ID:
        return "short";

      case StoredFormatIds.TINYINT_TYPE_ID:
        return "byte";

      case StoredFormatIds.DECIMAL_TYPE_ID:
      default:
        if (SanityManager.DEBUG) {
          SanityManager.THROWASSERT(
              "unexpected formatId in getCorrespondingPrimitiveTypeName() - " + formatId);
        }
        return null;
    }
  }
  /** @see TypeCompiler#getCastToCharWidth */
  public int getCastToCharWidth(DataTypeDescriptor dts) {
    int formatId = getStoredFormatIdFromTypeId();
    switch (formatId) {
      case StoredFormatIds.DECIMAL_TYPE_ID:
        // Need to have space for '-' and decimal point.
        return dts.getPrecision() + 2;

      case StoredFormatIds.DOUBLE_TYPE_ID:
        return TypeCompiler.DOUBLE_MAXWIDTH_AS_CHAR;

      case StoredFormatIds.INT_TYPE_ID:
        return TypeCompiler.INT_MAXWIDTH_AS_CHAR;

      case StoredFormatIds.LONGINT_TYPE_ID:
        return TypeCompiler.LONGINT_MAXWIDTH_AS_CHAR;

      case StoredFormatIds.REAL_TYPE_ID:
        return TypeCompiler.REAL_MAXWIDTH_AS_CHAR;

      case StoredFormatIds.SMALLINT_TYPE_ID:
        return TypeCompiler.SMALLINT_MAXWIDTH_AS_CHAR;

      case StoredFormatIds.TINYINT_TYPE_ID:
        return TypeCompiler.TINYINT_MAXWIDTH_AS_CHAR;

      default:
        if (SanityManager.DEBUG) {
          SanityManager.THROWASSERT("unexpected formatId in getCastToCharWidth() - " + formatId);
        }
        return 0;
    }
  }
Exemplo n.º 9
0
  /**
   * Called when setting a DECIMAL value internally or from through a procedure or function. Handles
   * long in addition to BigDecimal to handle identity being stored as a long but returned as a
   * DECIMAL.
   */
  public void setValue(Number theValue) throws StandardException {
    if (SanityManager.ASSERT) {
      if (theValue != null
          && !(theValue instanceof java.math.BigDecimal)
          && !(theValue instanceof java.lang.Long))
        SanityManager.THROWASSERT("SQLDecimal.setValue(Number) passed a " + theValue.getClass());
    }

    if (theValue instanceof BigDecimal || theValue == null) setCoreValue((BigDecimal) theValue);
    else setValue(theValue.longValue());
  }
Exemplo n.º 10
0
  /**
   * Flatten this FSqry into the outer query block. The steps in flattening are: o Mark all
   * ResultColumns as redundant, so that they are "skipped over" at generate(). o Append the
   * wherePredicates to the outer list. o Return the fromList so that the caller will merge the 2
   * lists RESOLVE - FSqrys with subqueries are currently not flattenable. Some of them can be
   * flattened, however. We need to merge the subquery list when we relax this restriction.
   *
   * <p>NOTE: This method returns NULL when flattening RowResultSetNodes (the node for a VALUES
   * clause). The reason is that no reference is left to the RowResultSetNode after flattening is
   * done - the expressions point directly to the ValueNodes in the RowResultSetNode's
   * ResultColumnList.
   *
   * @param rcl The RCL from the outer query
   * @param outerPList PredicateList to append wherePredicates to.
   * @param sql The SubqueryList from the outer query
   * @param gbl The group by list, if any
   * @param havingClause The HAVING clause, if any
   * @return FromList The fromList from the underlying SelectNode.
   * @exception StandardException Thrown on error
   */
  public FromList flatten(
      ResultColumnList rcl,
      PredicateList outerPList,
      SubqueryList sql,
      GroupByList gbl,
      ValueNode havingClause)
      throws StandardException {
    FromList fromList = null;
    SelectNode selectNode;

    resultColumns.setRedundant();

    subquery.getResultColumns().setRedundant();

    /*
     ** RESOLVE: Each type of result set should know how to remap itself.
     */
    if (subquery instanceof SelectNode) {
      selectNode = (SelectNode) subquery;
      fromList = selectNode.getFromList();

      // selectNode.getResultColumns().setRedundant();

      if (selectNode.getWherePredicates().size() > 0) {
        outerPList.destructiveAppend(selectNode.getWherePredicates());
      }

      if (selectNode.getWhereSubquerys().size() > 0) {
        sql.destructiveAppend(selectNode.getWhereSubquerys());
      }
    } else if (!(subquery instanceof RowResultSetNode)) {
      if (SanityManager.DEBUG) {
        SanityManager.THROWASSERT(
            "subquery expected to be either a SelectNode or a RowResultSetNode, but is a "
                + subquery.getClass().getName());
      }
    }

    /* Remap all ColumnReferences from the outer query to this node.
     * (We replace those ColumnReferences with clones of the matching
     * expression in the SELECT's RCL.
     */
    rcl.remapColumnReferencesToExpressions();
    outerPList.remapColumnReferencesToExpressions();
    if (gbl != null) {
      gbl.remapColumnReferencesToExpressions();
    }

    if (havingClause != null) {
      havingClause.remapColumnReferencesToExpressions();
    }

    return fromList;
  }
  /**
   * Write the old column value and and new column value as optional data. If logical undo, writes
   * out the entire row's before image.
   *
   * @exception IOException Can be thrown by any of the methods of ObjectOutput.
   * @exception StandardException Standard Derby policy.
   */
  private void writeOptionalDataToBuffer(RawTransaction t, Object column)
      throws StandardException, IOException {

    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(this.page != null);
    }

    DynamicByteArrayOutputStream logBuffer = t.getLogBuffer();
    int optionalDataStart = logBuffer.getPosition();

    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(
          optionalDataStart == 0, "Buffer for writing optional data should start at position 0");
    }

    this.page.logColumn(doMeSlot, fieldId, column, logBuffer, 100); // the after image of the column
    this.page.logField(doMeSlot, fieldId, logBuffer); // the BI of the column
    if (undo != null) {
      // RESOLVE: we want the AFTER image of the row, not the BEFORE
      // image.   This works for now because only btree needs a logical
      // undoable updateField and it always update only the pointer field
      // to point to something else.
      //
      // But in the future, it needs to be changed.

      this.page.logRecord(
          doMeSlot,
          BasePage.LOG_RECORD_DEFAULT,
          recordId,
          (FormatableBitSet) null,
          logBuffer,
          (RecordHandle) null);
      // log the BI of the entire row

    }

    int optionalDataLength = logBuffer.getPosition() - optionalDataStart;

    if (SanityManager.DEBUG) {
      if (optionalDataLength != logBuffer.getUsed())
        SanityManager.THROWASSERT(
            "wrong optional data length, optionalDataLength = "
                + optionalDataLength
                + ", logBuffer.getUsed() = "
                + logBuffer.getUsed());
    }

    // set the position to the beginning of the buffer
    logBuffer.setPosition(optionalDataStart);

    this.preparedLog =
        new ByteArray(logBuffer.getByteArray(), optionalDataStart, optionalDataLength);
  }
Exemplo n.º 12
0
  /**
   * Restore the in-memory representation from the stream.
   *
   * <p>
   *
   * @exception ClassNotFoundException Thrown if the stored representation is serialized and a class
   *     named in the stream could not be found.
   * @see java.io.Externalizable#readExternal
   */
  private final void localReadExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    super.readExternal(in);
    baseConglomerateId = in.readLong();
    rowLocationColumn = in.readInt();

    // read the column sort order info
    FormatableBitSet ascDescBits = new FormatableBitSet();
    ascDescBits.readExternal(in);
    ascDescInfo = new boolean[ascDescBits.getLength()];
    for (int i = 0; i < ascDescBits.getLength(); i++) ascDescInfo[i] = ascDescBits.isSet(i);

    // In memory maintain a collation id per column in the template.
    collation_ids = new int[format_ids.length];
    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(!hasCollatedTypes);
    }

    // initialize all the entries to COLLATION_TYPE_UCS_BASIC,
    // and then reset as necessary.  For version ACCESS_B2I_V3_ID,
    // this is the default and no resetting is necessary.
    for (int i = 0; i < format_ids.length; i++)
      collation_ids[i] = StringDataValue.COLLATION_TYPE_UCS_BASIC;

    // initialize the unique with null setting to false, to be reset
    // below when read from disk.  For version ACCESS_B2I_V3_ID and
    // ACCESS_B2I_V4_ID, this is the default and no resetting is necessary.
    setUniqueWithDuplicateNulls(false);

    if (conglom_format_id == StoredFormatIds.ACCESS_B2I_V4_ID
        || conglom_format_id == StoredFormatIds.ACCESS_B2I_V5_ID) {
      // current format id, read collation info from disk
      if (SanityManager.DEBUG) {
        // length must include row location column and at least
        // one other field.
        SanityManager.ASSERT(collation_ids.length >= 2, "length = " + collation_ids.length);
      }

      hasCollatedTypes = ConglomerateUtil.readCollationIdArray(collation_ids, in);
    } else if (conglom_format_id != StoredFormatIds.ACCESS_B2I_V3_ID) {
      // Currently only V3, V4 and V5 should be possible in a Derby DB.
      // Actual work for V3 is handled by default code above, so no
      // special work is necessary.

      if (SanityManager.DEBUG) {
        SanityManager.THROWASSERT("Unexpected format id: " + conglom_format_id);
      }
    }
    if (conglom_format_id == StoredFormatIds.ACCESS_B2I_V5_ID) {
      setUniqueWithDuplicateNulls(in.readBoolean());
    }
  }
Exemplo n.º 13
0
  /**
   * Distill the BigDecimal to a byte array and write out:
   *
   * <UL>
   *   <LI>scale (zero or positive) as a byte
   *   <LI>length of byte array as a byte
   *   <LI>the byte array
   * </UL>
   */
  public void writeExternal(ObjectOutput out) throws IOException {
    // never called when value is null
    if (SanityManager.DEBUG) SanityManager.ASSERT(!isNull());

    int scale;
    byte[] byteArray;

    if (value != null) {
      scale = value.scale();

      // J2SE 5.0 introduced negative scale value for BigDecimals.
      // In previouse Java releases a negative scale was not allowed
      // (threw an exception on setScale and the constructor that took
      // a scale).
      //
      // Thus the Derby format for DECIMAL implictly assumed a
      // positive or zero scale value, and thus now must explicitly
      // be positive. This is to allow databases created under J2SE 5.0
      // to continue to be supported under JDK 1.3/JDK 1.4, ie. to continue
      // the platform independence, independent of OS/cpu and JVM.
      //
      // If the scale is negative set the scale to be zero, this results
      // in an unchanged value with a new scale. A BigDecimal with a
      // negative scale by definition is a whole number.
      // e.g. 1000 can be represented by:
      //    a BigDecimal with scale -3 (unscaled value of 1)
      // or a BigDecimal with scale 0 (unscaled value of 1000)

      if (scale < 0) {
        scale = 0;
        value = value.setScale(0);
      }

      BigInteger bi = value.unscaledValue();
      byteArray = bi.toByteArray();
    } else {
      scale = rawScale;
      byteArray = rawData;
    }

    if (SanityManager.DEBUG) {
      if (scale < 0)
        SanityManager.THROWASSERT(
            "DECIMAL scale at writeExternal is negative " + scale + " value " + toString());
    }

    out.writeByte(scale);
    out.writeByte(byteArray.length);
    out.write(byteArray);
  }
Exemplo n.º 14
0
  /**
   * Initializer for a CreateTableNode for a base table
   *
   * @param newObjectName The name of the new object being created (ie base table)
   * @param tableElementList The elements of the table: columns, constraints, etc.
   * @param properties The optional list of properties associated with the table.
   * @param lockGranularity The lock granularity.
   * @exception StandardException Thrown on error
   */
  public void init(
      Object newObjectName, Object tableElementList, Object properties, Object lockGranularity)
      throws StandardException {
    tableType = TableDescriptor.BASE_TABLE_TYPE;
    this.lockGranularity = ((Character) lockGranularity).charValue();
    implicitCreateSchema = true;

    if (SanityManager.DEBUG) {
      if (this.lockGranularity != TableDescriptor.TABLE_LOCK_GRANULARITY
          && this.lockGranularity != TableDescriptor.ROW_LOCK_GRANULARITY) {
        SanityManager.THROWASSERT("Unexpected value for lockGranularity = " + this.lockGranularity);
      }
    }

    initAndCheck(newObjectName);
    this.tableElementList = (TableElementList) tableElementList;
    this.properties = (Properties) properties;
  }
  private int getDefaultAccessLevel() throws StandardException {
    PersistentSet tc = lcc.getTransactionExecute();

    String modeS =
        (String) PropertyUtil.getServiceProperty(tc, Property.DEFAULT_CONNECTION_MODE_PROPERTY);
    if (modeS == null) return FULL_ACCESS;
    else if (StringUtil.SQLEqualsIgnoreCase(modeS, Property.NO_ACCESS)) return NO_ACCESS;
    else if (StringUtil.SQLEqualsIgnoreCase(modeS, Property.READ_ONLY_ACCESS)) return READ_ACCESS;
    else if (StringUtil.SQLEqualsIgnoreCase(modeS, Property.FULL_ACCESS)) return FULL_ACCESS;
    else {
      if (SanityManager.DEBUG)
        SanityManager.THROWASSERT(
            "Invalid value for property "
                + Property.DEFAULT_CONNECTION_MODE_PROPERTY
                + " "
                + modeS);
      return FULL_ACCESS;
    }
  }
Exemplo n.º 16
0
  /**
   * Initializer for a CreateTableNode for a global temporary table
   *
   * @param newObjectName The name of the new object being declared (ie temporary table)
   * @param tableElementList The elements of the table: columns, constraints, etc.
   * @param properties The optional list of properties associated with the table.
   * @param onCommitDeleteRows If true, on commit delete rows else on commit preserve rows of
   *     temporary table.
   * @param onRollbackDeleteRows If true, on rollback, delete rows from temp tables which were
   *     logically modified. true is the only supported value
   * @exception StandardException Thrown on error
   */
  public void init(
      Object newObjectName,
      Object tableElementList,
      Object properties,
      Object onCommitDeleteRows,
      Object onRollbackDeleteRows)
      throws StandardException {
    tableType = TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE;
    newObjectName = tempTableSchemaNameCheck(newObjectName);
    this.onCommitDeleteRows = ((Boolean) onCommitDeleteRows).booleanValue();
    this.onRollbackDeleteRows = ((Boolean) onRollbackDeleteRows).booleanValue();
    initAndCheck(newObjectName);
    this.tableElementList = (TableElementList) tableElementList;
    this.properties = (Properties) properties;

    if (SanityManager.DEBUG) {
      if (this.onRollbackDeleteRows == false) {
        SanityManager.THROWASSERT(
            "Unexpected value for onRollbackDeleteRows = " + this.onRollbackDeleteRows);
      }
    }
  }
Exemplo n.º 17
0
  /**
   * Does this trigger need to fire on this type of DML?
   *
   * @param stmtType the type of DML
   *     (StatementType.INSERT|StatementType.UPDATE|StatementType.DELETE)
   * @param modifiedCols the columns modified, or null for all
   * @return true/false
   * @exception StandardException on error
   */
  public boolean needsToFire(int stmtType, int[] modifiedCols) throws StandardException {

    if (SanityManager.DEBUG) {
      if (!((stmtType == StatementType.INSERT)
          || (stmtType == StatementType.BULK_INSERT_REPLACE)
          || (stmtType == StatementType.UPDATE)
          || (stmtType == StatementType.DELETE))) {
        SanityManager.THROWASSERT("invalid statement type " + stmtType);
      }
    }

    /*
     ** If we are disabled, we never fire
     */
    if (!isEnabled) {
      return false;
    }

    if (stmtType == StatementType.INSERT) {
      return (eventMask & TRIGGER_EVENT_INSERT) == eventMask;
    }
    if (stmtType == StatementType.DELETE) {
      return (eventMask & TRIGGER_EVENT_DELETE) == eventMask;
    }

    // this is a temporary restriction, but it may not be lifted
    // anytime soon.
    if (stmtType == StatementType.BULK_INSERT_REPLACE) {
      throw StandardException.newException(
          SQLState.LANG_NO_BULK_INSERT_REPLACE_WITH_TRIGGER,
          getTableDescriptor().getQualifiedName(),
          name);
    }

    // if update, only relevant if columns intersect
    return ((eventMask & TRIGGER_EVENT_UPDATE) == eventMask)
        && ConstraintDescriptor.doColumnsIntersect(modifiedCols, referencedCols);
  }
  /**
   * Get the constraint type out of the row.
   *
   * @param row The row from sysconstraints
   * @return int The constraint type as an int
   * @exception StandardException thrown on failure
   */
  protected int getConstraintType(ExecRow row) throws StandardException {
    DataValueDescriptor col;
    int constraintIType;
    String constraintSType;

    /* 4th column is TYPE (char(1)) */
    col = row.getColumn(SYSCONSTRAINTS_TYPE);
    constraintSType = col.getString();
    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(constraintSType.length() == 1, "Fourth column type incorrect");
    }

    switch (constraintSType.charAt(0)) {
      case 'P':
        constraintIType = DataDictionary.PRIMARYKEY_CONSTRAINT;
        break;

      case 'U':
        constraintIType = DataDictionary.UNIQUE_CONSTRAINT;
        break;

      case 'C':
        constraintIType = DataDictionary.CHECK_CONSTRAINT;
        break;

      case 'F':
        constraintIType = DataDictionary.FOREIGNKEY_CONSTRAINT;
        break;

      default:
        if (SanityManager.DEBUG) {
          SanityManager.THROWASSERT("Fourth column value invalid");
        }
        constraintIType = -1;
    }

    return constraintIType;
  }
  /**
   * @see Authorizer#authorize
   * @exception StandardException Thrown if the operation is not allowed
   */
  public void authorize(Activation activation, int operation) throws StandardException {
    int sqlAllowed = lcc.getStatementContext().getSQLAllowed();

    switch (operation) {
      case Authorizer.SQL_ARBITARY_OP:
      case Authorizer.SQL_CALL_OP:
        if (sqlAllowed == RoutineAliasInfo.NO_SQL)
          throw externalRoutineException(operation, sqlAllowed);
        break;
      case Authorizer.SQL_SELECT_OP:
        if (sqlAllowed > RoutineAliasInfo.READS_SQL_DATA)
          throw externalRoutineException(operation, sqlAllowed);
        break;

        // SQL write operations
      case Authorizer.SQL_WRITE_OP:
      case Authorizer.PROPERTY_WRITE_OP:
        if (isReadOnlyConnection())
          throw StandardException.newException(SQLState.AUTH_WRITE_WITH_READ_ONLY_CONNECTION);
        if (sqlAllowed > RoutineAliasInfo.MODIFIES_SQL_DATA)
          throw externalRoutineException(operation, sqlAllowed);
        break;

        // SQL DDL operations
      case Authorizer.JAR_WRITE_OP:
      case Authorizer.SQL_DDL_OP:
        if (isReadOnlyConnection())
          throw StandardException.newException(SQLState.AUTH_DDL_WITH_READ_ONLY_CONNECTION);

        if (sqlAllowed > RoutineAliasInfo.MODIFIES_SQL_DATA)
          throw externalRoutineException(operation, sqlAllowed);
        break;

      default:
        if (SanityManager.DEBUG) SanityManager.THROWASSERT("Bad operation code " + operation);
    }
    if (activation != null) {
      List requiredPermissionsList = activation.getPreparedStatement().getRequiredPermissionsList();
      DataDictionary dd = lcc.getDataDictionary();

      // Database Owner can access any object. Ignore
      // requiredPermissionsList for Database Owner
      if (requiredPermissionsList != null
          && !requiredPermissionsList.isEmpty()
          && !authorizationId.equals(dd.getAuthorizationDatabaseOwner())) {
        int ddMode = dd.startReading(lcc);

        /*
         * The system may need to read the permission descriptor(s)
         * from the system table(s) if they are not available in the
         * permission cache.  So start an internal read-only nested
         * transaction for this.
         *
         * The reason to use a nested transaction here is to not hold
         * locks on system tables on a user transaction.  e.g.:  when
         * attempting to revoke an user, the statement may time out
         * since the user-to-be-revoked transaction may have acquired
         * shared locks on the permission system tables; hence, this
         * may not be desirable.
         *
         * All locks acquired by StatementPermission object's check()
         * method will be released when the system ends the nested
         * transaction.
         *
         * In Derby, the locks from read nested transactions come from
         * the same space as the parent transaction; hence, they do not
         * conflict with parent locks.
         */
        lcc.beginNestedTransaction(true);

        try {
          try {
            // perform the permission checking
            for (Iterator iter = requiredPermissionsList.iterator(); iter.hasNext(); ) {
              ((StatementPermission) iter.next()).check(lcc, authorizationId, false, activation);
            }
          } finally {
            dd.doneReading(ddMode, lcc);
          }
        } finally {
          // make sure we commit; otherwise, we will end up with
          // mismatch nested level in the language connection context.
          lcc.commitNestedTransaction();
        }
      }
    }
  }
  /**
   * Make a ConstraintDescriptor out of a SYSCONSTRAINTS row
   *
   * @param row a SYSCONSTRAINTS row
   * @param parentTupleDescriptor Subconstraint descriptor with auxiliary info.
   * @param dd dataDictionary
   * @exception StandardException thrown on failure
   */
  public TupleDescriptor buildDescriptor(
      ExecRow row, TupleDescriptor parentTupleDescriptor, DataDictionary dd)
      throws StandardException {
    ConstraintDescriptor constraintDesc = null;

    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(
          row.nColumns() == SYSCONSTRAINTS_COLUMN_COUNT,
          "Wrong number of columns for a SYSCONSTRAINTS row");
    }

    DataValueDescriptor col;
    ConglomerateDescriptor conglomDesc;
    DataDescriptorGenerator ddg;
    TableDescriptor td = null;
    int constraintIType = -1;
    int[] keyColumns = null;
    UUID constraintUUID;
    UUID schemaUUID;
    UUID tableUUID;
    UUID referencedConstraintId = null;
    SchemaDescriptor schema;
    String tableUUIDString;
    String constraintName;
    String constraintSType;
    String constraintStateStr;
    boolean constraintEnabled;
    int referenceCount;
    String constraintUUIDString;
    String schemaUUIDString;
    SubConstraintDescriptor scd;

    if (SanityManager.DEBUG) {
      if (!(parentTupleDescriptor instanceof SubConstraintDescriptor)) {
        SanityManager.THROWASSERT(
            "parentTupleDescriptor expected to be instanceof "
                + "SubConstraintDescriptor, not "
                + parentTupleDescriptor.getClass().getName());
      }
    }

    scd = (SubConstraintDescriptor) parentTupleDescriptor;

    ddg = dd.getDataDescriptorGenerator();

    /* 1st column is CONSTRAINTID (UUID - char(36)) */
    col = row.getColumn(SYSCONSTRAINTS_CONSTRAINTID);
    constraintUUIDString = col.getString();
    constraintUUID = getUUIDFactory().recreateUUID(constraintUUIDString);

    /* 2nd column is TABLEID (UUID - char(36)) */
    col = row.getColumn(SYSCONSTRAINTS_TABLEID);
    tableUUIDString = col.getString();
    tableUUID = getUUIDFactory().recreateUUID(tableUUIDString);

    /* Get the TableDescriptor.
     * It may be cached in the SCD,
     * otherwise we need to go to the
     * DD.
     */
    if (scd != null) {
      td = scd.getTableDescriptor();
    }
    if (td == null) {
      td = dd.getTableDescriptor(tableUUID);
    }

    /* 3rd column is NAME (varchar(128)) */
    col = row.getColumn(SYSCONSTRAINTS_CONSTRAINTNAME);
    constraintName = col.getString();

    /* 4th column is TYPE (char(1)) */
    col = row.getColumn(SYSCONSTRAINTS_TYPE);
    constraintSType = col.getString();
    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(constraintSType.length() == 1, "Fourth column type incorrect");
    }

    boolean typeSet = false;
    switch (constraintSType.charAt(0)) {
      case 'P':
        constraintIType = DataDictionary.PRIMARYKEY_CONSTRAINT;
        typeSet = true;
        // fall through

      case 'U':
        if (!typeSet) {
          constraintIType = DataDictionary.UNIQUE_CONSTRAINT;
          typeSet = true;
        }
        // fall through

      case 'F':
        if (!typeSet) constraintIType = DataDictionary.FOREIGNKEY_CONSTRAINT;
        if (SanityManager.DEBUG) {
          if (!(parentTupleDescriptor instanceof SubKeyConstraintDescriptor)) {
            SanityManager.THROWASSERT(
                "parentTupleDescriptor expected to be instanceof "
                    + "SubKeyConstraintDescriptor, not "
                    + parentTupleDescriptor.getClass().getName());
          }
        }
        conglomDesc =
            td.getConglomerateDescriptor(
                ((SubKeyConstraintDescriptor) parentTupleDescriptor).getIndexId());
        /* Take care the rare case of conglomDesc being null.  The
         * reason is that our "td" is out of date.  Another thread
         * which was adding a constraint committed between the moment
         * we got the table descriptor (conglomerate list) and the
         * moment we scanned and got the constraint desc list.  Since
         * that thread just added a new row to SYSCONGLOMERATES,
         * SYSCONSTRAINTS, etc.  We wouldn't have wanted to lock the
         * system tables just to prevent other threads from adding new
         * rows.
         */
        if (conglomDesc == null) {
          // we can't be getting td from cache because if we are
          // here, we must have been in dd's ddl mode (that's why
          // the ddl thread went through), we are not done yet, the
          // dd ref count is not 0, hence it couldn't have turned
          // into COMPILE_ONLY mode
          td = dd.getTableDescriptor(tableUUID);
          if (scd != null) scd.setTableDescriptor(td);
          // try again now
          conglomDesc =
              td.getConglomerateDescriptor(
                  ((SubKeyConstraintDescriptor) parentTupleDescriptor).getIndexId());
        }

        if (SanityManager.DEBUG) {
          SanityManager.ASSERT(
              conglomDesc != null, "conglomDesc is expected to be non-null for backing index");
        }
        keyColumns = conglomDesc.getIndexDescriptor().baseColumnPositions();
        referencedConstraintId =
            ((SubKeyConstraintDescriptor) parentTupleDescriptor).getKeyConstraintId();
        keyColumns = conglomDesc.getIndexDescriptor().baseColumnPositions();
        break;

      case 'C':
        constraintIType = DataDictionary.CHECK_CONSTRAINT;
        if (SanityManager.DEBUG) {
          if (!(parentTupleDescriptor instanceof SubCheckConstraintDescriptor)) {
            SanityManager.THROWASSERT(
                "parentTupleDescriptor expected to be instanceof "
                    + "SubCheckConstraintDescriptor, not "
                    + parentTupleDescriptor.getClass().getName());
          }
        }
        break;

      default:
        if (SanityManager.DEBUG) {
          SanityManager.THROWASSERT("Fourth column value invalid");
        }
    }

    /* 5th column is SCHEMAID (UUID - char(36)) */
    col = row.getColumn(SYSCONSTRAINTS_SCHEMAID);
    schemaUUIDString = col.getString();
    schemaUUID = getUUIDFactory().recreateUUID(schemaUUIDString);

    schema = dd.getSchemaDescriptor(schemaUUID, null);

    /* 6th column is STATE (char(1)) */
    col = row.getColumn(SYSCONSTRAINTS_STATE);
    constraintStateStr = col.getString();
    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(constraintStateStr.length() == 1, "Sixth column (state) type incorrect");
    }

    switch (constraintStateStr.charAt(0)) {
      case 'E':
        constraintEnabled = true;
        break;
      case 'D':
        constraintEnabled = false;
        break;
      default:
        constraintEnabled = true;
        if (SanityManager.DEBUG) {
          SanityManager.THROWASSERT(
              "Invalidate state value '" + constraintStateStr + "' for constraint");
        }
    }

    /* 7th column is REFERENCECOUNT, boolean */
    col = row.getColumn(SYSCONSTRAINTS_REFERENCECOUNT);
    referenceCount = col.getInt();

    /* now build and return the descriptor */

    switch (constraintIType) {
      case DataDictionary.PRIMARYKEY_CONSTRAINT:
        constraintDesc =
            ddg.newPrimaryKeyConstraintDescriptor(
                td,
                constraintName,
                false, // deferable,
                false, // initiallyDeferred,
                keyColumns, // genReferencedColumns(dd, td), //int referencedColumns[],
                constraintUUID,
                ((SubKeyConstraintDescriptor) parentTupleDescriptor).getIndexId(),
                schema,
                constraintEnabled,
                referenceCount);
        break;

      case DataDictionary.UNIQUE_CONSTRAINT:
        constraintDesc =
            ddg.newUniqueConstraintDescriptor(
                td,
                constraintName,
                false, // deferable,
                false, // initiallyDeferred,
                keyColumns, // genReferencedColumns(dd, td), //int referencedColumns[],
                constraintUUID,
                ((SubKeyConstraintDescriptor) parentTupleDescriptor).getIndexId(),
                schema,
                constraintEnabled,
                referenceCount);
        break;

      case DataDictionary.FOREIGNKEY_CONSTRAINT:
        if (SanityManager.DEBUG) {
          SanityManager.ASSERT(
              referenceCount == 0, "REFERENCECOUNT column is nonzero for fk constraint");
        }

        constraintDesc =
            ddg.newForeignKeyConstraintDescriptor(
                td,
                constraintName,
                false, // deferable,
                false, // initiallyDeferred,
                keyColumns, // genReferencedColumns(dd, td), //int referencedColumns[],
                constraintUUID,
                ((SubKeyConstraintDescriptor) parentTupleDescriptor).getIndexId(),
                schema,
                referencedConstraintId,
                constraintEnabled,
                ((SubKeyConstraintDescriptor) parentTupleDescriptor).getRaDeleteRule(),
                ((SubKeyConstraintDescriptor) parentTupleDescriptor).getRaUpdateRule());
        break;

      case DataDictionary.CHECK_CONSTRAINT:
        if (SanityManager.DEBUG) {
          SanityManager.ASSERT(
              referenceCount == 0, "REFERENCECOUNT column is nonzero for check constraint");
        }

        constraintDesc =
            ddg.newCheckConstraintDescriptor(
                td,
                constraintName,
                false, // deferable,
                false, // initiallyDeferred,
                constraintUUID,
                ((SubCheckConstraintDescriptor) parentTupleDescriptor).getConstraintText(),
                ((SubCheckConstraintDescriptor) parentTupleDescriptor)
                    .getReferencedColumnsDescriptor(),
                schema,
                constraintEnabled);
        break;
    }
    return constraintDesc;
  }
Exemplo n.º 21
0
  /**
   * ************************************************************************ Private methods of
   * B2I, arranged alphabetically.
   * *************************************************************************
   */
  private void traverseRight() {
    // RESOLVE - Do I have to do this???????????????

    if (SanityManager.DEBUG) SanityManager.THROWASSERT("not implemented.");
  }
  /**
   * Make a SYSCONTRAINTS row
   *
   * @return Row suitable for inserting into SYSCONTRAINTS.
   * @exception StandardException thrown on failure
   */
  public ExecRow makeRow(TupleDescriptor td, TupleDescriptor parent) throws StandardException {
    DataValueDescriptor col;
    ExecRow row;
    int constraintIType;
    UUID oid;
    String constraintSType = null;
    String constraintID = null;
    String tableID = null;
    String constraintName = null;
    String schemaID = null;
    boolean isEnabled = true;
    int referenceCount = 0;

    if (td != null) {
      ConstraintDescriptor constraint = (ConstraintDescriptor) td;
      /*
       ** We only allocate a new UUID if the descriptor doesn't already have one.
       ** For descriptors replicated from a Source system, we already have an UUID.
       */
      oid = constraint.getUUID();
      constraintID = oid.toString();

      oid = constraint.getTableId();
      tableID = oid.toString();

      constraintName = constraint.getConstraintName();

      constraintIType = constraint.getConstraintType();
      switch (constraintIType) {
        case DataDictionary.PRIMARYKEY_CONSTRAINT:
          constraintSType = "P";
          break;

        case DataDictionary.UNIQUE_CONSTRAINT:
          constraintSType = "U";
          break;

        case DataDictionary.CHECK_CONSTRAINT:
          constraintSType = "C";
          break;

        case DataDictionary.FOREIGNKEY_CONSTRAINT:
          constraintSType = "F";
          break;

        default:
          if (SanityManager.DEBUG) {
            SanityManager.THROWASSERT("invalid constraint type");
          }
      }

      schemaID = constraint.getSchemaDescriptor().getUUID().toString();
      isEnabled = constraint.isEnabled();
      referenceCount = constraint.getReferenceCount();
    }

    /* Insert info into sysconstraints */

    /* RESOLVE - It would be nice to require less knowledge about sysconstraints
     * and have this be more table driven.
     */

    /* Build the row to insert  */
    row = getExecutionFactory().getValueRow(SYSCONSTRAINTS_COLUMN_COUNT);

    /* 1st column is CONSTRAINTID (UUID - char(36)) */
    row.setColumn(SYSCONSTRAINTS_CONSTRAINTID, new SQLChar(constraintID));

    /* 2nd column is TABLEID (UUID - char(36)) */
    row.setColumn(SYSCONSTRAINTS_TABLEID, new SQLChar(tableID));

    /* 3rd column is NAME (varchar(128)) */
    row.setColumn(SYSCONSTRAINTS_CONSTRAINTNAME, new SQLVarchar(constraintName));

    /* 4th column is TYPE (char(1)) */
    row.setColumn(SYSCONSTRAINTS_TYPE, new SQLChar(constraintSType));

    /* 5th column is SCHEMAID (UUID - char(36)) */
    row.setColumn(SYSCONSTRAINTS_SCHEMAID, new SQLChar(schemaID));

    /* 6th column is STATE (char(1)) */
    row.setColumn(SYSCONSTRAINTS_STATE, new SQLChar(isEnabled ? "E" : "D"));

    /* 7th column is REFERENCED */
    row.setColumn(SYSCONSTRAINTS_REFERENCECOUNT, dvf.getDataValue(referenceCount));

    return row;
  }
Exemplo n.º 23
0
  /**
   * Create an empty secondary index b-tree, using the generic b-tree to do the generic part of the
   * creation process.
   *
   * <p>This routine opens the newly created container, adds a single page, and makes this page the
   * root by inserting a LeafControlRow onto this page at slot 0 and marking in that control row
   * that the page is a root page.
   *
   * <p>The following properties are specific to the b-tree secondary index:
   *
   * <UL>
   *   <LI>"baseConglomerateId" (integer). The conglomerate id of the base conglomerate is never
   *       actually accessed by the b-tree secondary index implementation, it only serves as a
   *       namespace for row locks. This property is required.
   *   <LI>"rowLocationColumn" (integer). The zero-based index into the row which the b-tree
   *       secondary index will assume holds a @see RowLocation of the base row in the base
   *       conglomerate. This value will be used for acquiring locks. In this implementation
   *       RowLocationColumn must be the last key column. This property is required.
   * </UL>
   *
   * A secondary index i (a, b) on table t (a, b, c) would have rows which looked like (a, b,
   * row_location). baseConglomerateId is set to the conglomerate id of t. rowLocationColumns is set
   * to 2. allowsDuplicates would be set to false, @see BTree#create. To create a unique secondary
   * index set uniquenessColumns to 2, this means that the btree code will compare the key values
   * but not the row id when determing uniqueness. To create a nonunique secondary index set
   * uniquenessColumns to 3, this would mean that the uniqueness test would include the row location
   * and since all row locations will be unique all rows inserted into the index will be
   * differentiated (at least) by row location.
   *
   * @see BTree#create
   * @exception StandardException Standard exception policy.
   */
  public void create(
      TransactionManager xact_manager,
      int segmentId,
      long input_conglomid,
      DataValueDescriptor[] template,
      ColumnOrdering[] columnOrder,
      int[] collationIds,
      Properties properties,
      int temporaryFlag)
      throws StandardException {
    String property_value = null;
    Transaction rawtran = xact_manager.getRawStoreXact();

    if (properties == null) {
      throw (StandardException.newException(
          SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
    }

    // Get baseConglomerateId //
    property_value = properties.getProperty(PROPERTY_BASECONGLOMID);
    if (property_value == null) {
      throw (StandardException.newException(
          SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
    }

    if (SanityManager.DEBUG) {
      if (property_value == null)
        SanityManager.THROWASSERT(PROPERTY_BASECONGLOMID + "property not passed to B2I.create()");
    }

    baseConglomerateId = Long.parseLong(property_value);

    // Get rowLocationColumn //
    property_value = properties.getProperty(PROPERTY_ROWLOCCOLUMN);

    if (SanityManager.DEBUG) {
      if (property_value == null)
        SanityManager.THROWASSERT(PROPERTY_ROWLOCCOLUMN + "property not passed to B2I.create()");
    }

    if (property_value == null) {
      throw (StandardException.newException(
          SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
    }

    rowLocationColumn = Integer.parseInt(property_value);

    // Currently the row location column must be the last column (makes)
    // comparing the columns in the index easier.
    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(
          rowLocationColumn == template.length - 1,
          "rowLocationColumn is not the last column in the index");
      SanityManager.ASSERT(template[rowLocationColumn] instanceof RowLocation);

      // There must be at least one key column
      if (rowLocationColumn < 1)
        SanityManager.THROWASSERT(
            "rowLocationColumn (" + rowLocationColumn + ") expected to be >= 1");
    }

    /* convert the sorting order information into a boolean array map.
     * If the sorting order for the columns is not provided, we
     * assign the default as Ascending Order.
     * array length is equal to template length, because column order
     * length changes whether it is unique or is non unique. store assumes
     * template length arrays. So, we make template length array and make
     * the last column as ascending instead of having lot of execeptions
     * code.
     */

    ascDescInfo = new boolean[template.length];
    for (int i = 0; i < ascDescInfo.length; i++) {
      if (columnOrder != null && i < columnOrder.length)
        ascDescInfo[i] = columnOrder[i].getIsAscending();
      else ascDescInfo[i] = true; // default values - ascending order
    }

    // get collation ids from input collation ids, store it in the
    // conglom state.
    collation_ids = ConglomerateUtil.createCollationIds(template.length, collationIds);
    hasCollatedTypes = hasCollatedColumns(collation_ids);

    // Do the generic part of creating the b-tree.
    super.create(
        rawtran,
        segmentId,
        input_conglomid,
        template,
        properties,
        getTypeFormatId(),
        temporaryFlag);

    // open the base conglomerate - to get the lock
    ConglomerateController base_cc =
        xact_manager.openConglomerate(
            baseConglomerateId,
            false,
            TransactionController.OPENMODE_FOR_LOCK_ONLY,
            TransactionController.MODE_TABLE,
            TransactionController.ISOLATION_SERIALIZABLE);

    OpenBTree open_btree = new OpenBTree();

    BTreeLockingPolicy b2i_locking_policy =
        new B2ITableLocking3(
            rawtran,
            TransactionController.MODE_TABLE,
            rawtran.newLockingPolicy(
                LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true),
            base_cc,
            open_btree);

    // The following call will "open" the new btree.  Create is
    // an interesting case.  What we really want is read only table lock
    // on the base conglomerate and update locks on the index.  For now
    // just get the update lock on the base table, this is done by the
    // lockTable() call made by base class.

    open_btree.init(
        (TransactionManager) xact_manager, // current user xact
        (TransactionManager) xact_manager, // current xact
        (ContainerHandle) null, // have init open the container.
        rawtran,
        false,
        (ContainerHandle.MODE_FORUPDATE),
        TransactionController.MODE_TABLE,
        b2i_locking_policy, // get table level lock.
        this,
        (LogicalUndo) null, // no logical undo necessary, as
        // initEmptyBtree()
        // work will be done single user and
        // rows will not move.
        (DynamicCompiledOpenConglomInfo) null);

    // Open the newly created container, and insert the first control row.
    LeafControlRow.initEmptyBtree(open_btree);

    open_btree.close();

    base_cc.close();
  }