@Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   tuple.getKey(ptr);
   int offset = accessor.getOffset(ptr.get(), ptr.getOffset());
   // Null is represented in the last expression of a multi-part key
   // by the bytes not being present.
   if (offset < ptr.getOffset() + ptr.getLength()) {
     byte[] buffer = ptr.get();
     int maxByteSize = ptr.getLength() - (offset - ptr.getOffset());
     int fixedByteSize = -1;
     // FIXME: fixedByteSize <= maxByteSize ? fixedByteSize : 0 required because HBase passes bogus
     // keys to filter to position scan (HBASE-6562)
     if (fromType.isFixedWidth()) {
       fixedByteSize = getByteSize();
       fixedByteSize = fixedByteSize <= maxByteSize ? fixedByteSize : 0;
     }
     int length =
         fixedByteSize >= 0 ? fixedByteSize : accessor.getLength(buffer, offset, maxByteSize);
     // In the middle of the key, an empty variable length byte array represents null
     if (length > 0) {
       if (type == fromType) {
         ptr.set(buffer, offset, length);
       } else {
         ptr.set(type.toBytes(type.toObject(buffer, offset, length, fromType)));
       }
       return true;
     }
   }
   return false;
 }
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   // Starting from the end of the byte, look for all single bytes at the end of the string
   // that is below SPACE_UTF8 (space and control characters) or above (control chars).
   if (!getStringExpression().evaluate(tuple, ptr)) {
     return false;
   }
   if (ptr.getLength() == 0) {
     ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
     return true;
   }
   byte[] string = ptr.get();
   int offset = ptr.getOffset();
   int length = ptr.getLength();
   int i = offset + length - 1;
   for (; i >= offset; i--) {
     if ((string[i] & SINGLE_BYTE_MASK) == 0 && SPACE_UTF8 < string[i] && string[i] != 0x7f) {
       break;
     }
   }
   if (i == offset - 1) {
     ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
     return true;
   }
   ptr.set(string, offset, i - offset + 1);
   return true;
 }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    DateNative dateNative = DateNative.getInstance();
    for (int i = 0; i < children.size(); i++) {
      if (!children.get(i).evaluate(tuple, ptr) || ptr.getLength() == 0) {
        return false;
      }

      PDataType childType = children.get(i).getDataType();
      boolean isDate = childType.isCoercibleTo(PDataType.DATE);
      BigDecimal bd =
          isDate
              ? BigDecimal.valueOf(dateNative.toLong(ptr))
              : (BigDecimal) PDataType.DECIMAL.toObject(ptr, childType);

      if (result == null) {
        result = bd;
      } else {
        result = result.subtract(bd);
        /*
         * Special case for date subtraction - note that only first two expression may be dates.
         * We need to convert the date to a unit of "days" because that's what sql expects.
         */
        if (isDate) {
          result = result.divide(BD_MILLIS_IN_DAY, PDataType.DEFAULT_MATH_CONTEXT);
        }
      }
    }
    ptr.set(PDataType.DECIMAL.toBytes(result));
    return true;
  }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    for (int i = 0; i < children.size(); i++) {
      Expression childExpr = children.get(i);
      if (!childExpr.evaluate(tuple, ptr)) {
        return false;
      }
      if (ptr.getLength() == 0) {
        return true;
      }

      PDataType childType = children.get(i).getDataType();
      BigDecimal bd = (BigDecimal) PDataType.DECIMAL.toObject(ptr, childType);

      if (result == null) {
        result = bd;
      } else {
        result = result.divide(bd, PDataType.DEFAULT_MATH_CONTEXT);
      }
    }
    if (maxLength != null && scale != null) {
      result = NumberUtil.setDecimalWidthAndScale(result, maxLength, scale);
    }
    if (result == null) {
      throw new ValueTypeIncompatibleException(PDataType.DECIMAL, maxLength, scale);
    }
    ptr.set(PDataType.DECIMAL.toBytes(result));
    return true;
  }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if (!children.get(0).evaluate(tuple, ptr)) {
      return false;
    }

    String timezone = Bytes.toString(ptr.get(), ptr.getOffset(), ptr.getLength());

    if (!children.get(1).evaluate(tuple, ptr)) {
      return false;
    }

    if (!cachedTimeZones.containsKey(timezone)) {
      TimeZone tz = TimeZone.getTimeZone(timezone);
      if (!tz.getID().equals(timezone)) {
        throw new IllegalDataException("Invalid timezone " + timezone);
      }
      cachedTimeZones.put(timezone, tz);
    }

    Date date = (Date) PDate.INSTANCE.toObject(ptr, children.get(1).getSortOrder());
    int offset = cachedTimeZones.get(timezone).getOffset(date.getTime());

    ptr.set(PInteger.INSTANCE.toBytes(offset / MILLIS_TO_MINUTES));
    return true;
  }
Beispiel #6
0
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    // TODO: multi-byte characters
    Expression offsetExpression = getOffsetExpression();
    if (!offsetExpression.evaluate(tuple, ptr)) {
      return false;
    }
    LongNative longNative = (LongNative) offsetExpression.getDataType().getNative();
    int offset = (int) longNative.toLong(ptr);

    int length = -1;
    if (hasLengthExpression) {
      Expression lengthExpression = getLengthExpression();
      if (!lengthExpression.evaluate(tuple, ptr)) {
        return false;
      }
      longNative = (LongNative) lengthExpression.getDataType().getNative();
      length = (int) longNative.toLong(ptr);
      if (length <= 0) {
        return false;
      }
    }

    if (!getStrExpression().evaluate(tuple, ptr)) {
      return false;
    }

    try {
      boolean isCharType = getStrExpression().getDataType() == PDataType.CHAR;
      int strlen =
          isCharType
              ? ptr.getLength()
              : StringUtil.calculateUTF8Length(ptr.get(), ptr.getOffset(), ptr.getLength());

      // Account for 1 versus 0-based offset
      offset = offset - (offset <= 0 ? 0 : 1);
      if (offset < 0) { // Offset < 0 means get from end
        offset = strlen + offset;
      }
      if (offset < 0 || offset >= strlen) {
        return false;
      }
      int maxLength = strlen - offset;
      length = length == -1 ? maxLength : Math.min(length, maxLength);

      int byteOffset =
          isCharType
              ? offset
              : StringUtil.getByteLengthForUtf8SubStr(ptr.get(), ptr.getOffset(), offset);
      int byteLength =
          isCharType
              ? length
              : StringUtil.getByteLengthForUtf8SubStr(
                  ptr.get(), ptr.getOffset() + byteOffset, length);
      ptr.set(ptr.get(), ptr.getOffset() + byteOffset, byteLength);
      return true;
    } catch (UnsupportedEncodingException e) {
      return false;
    }
  }
Beispiel #7
0
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   Expression expression = getExpression();
   if (!expression.evaluate(tuple, ptr)) {
     return false;
   }
   PDataType type = expression.getDataType();
   Object value = formatter.format(type.toObject(ptr, expression.getSortOrder()));
   byte[] b = getDataType().toBytes(value);
   ptr.set(b);
   return true;
 }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if (!getChildExpression().evaluate(tuple, ptr)) {
      return false;
    }

    // Update the digest value
    messageDigest.update(ptr.get(), ptr.getOffset(), ptr.getLength());
    // Get the digest bytes (note this resets the messageDigest as well)
    ptr.set(messageDigest.digest());
    return true;
  }
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   if (!super.evaluate(tuple, ptr)) {
     return false;
   }
   if (isConstantExpression()) {
     PDataType type = getDataType();
     Object constantValue = ((LiteralExpression) children.get(0)).getValue();
     if (type == PDataType.DECIMAL) {
       BigDecimal value =
           ((BigDecimal) constantValue)
               .multiply((BigDecimal) PDataType.DECIMAL.toObject(ptr, PDataType.LONG));
       ptr.set(PDataType.DECIMAL.toBytes(value));
     } else {
       long constantLongValue = ((Number) constantValue).longValue();
       long value = constantLongValue * type.getCodec().decodeLong(ptr, null);
       ptr.set(new byte[type.getByteSize()]);
       type.getCodec().encodeLong(value, ptr);
     }
   }
   return true;
 }
Beispiel #10
0
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if (!getStringExpression().evaluate(tuple, ptr)) {
      return false;
    }
    if (ptr.getLength() == 0) {
      ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
      return true;
    }
    byte[] string = ptr.get();
    int offset = ptr.getOffset();
    int length = ptr.getLength();

    ColumnModifier columnModifier = getColumnModifier();
    int end = StringUtil.getFirstNonBlankCharIdxFromEnd(string, offset, length, columnModifier);
    if (end == offset - 1) {
      ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
      return true;
    }
    int head = StringUtil.getFirstNonBlankCharIdxFromStart(string, offset, length, columnModifier);
    ptr.set(string, head, end - head + 1);
    return true;
  }
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   Expression arg = getChildren().get(0);
   if (!arg.evaluate(tuple, ptr)) {
     return false;
   }
   if (ptr.getLength() == 0) {
     return true;
   }
   long dateTime = inputCodec.decodeLong(ptr, arg.getSortOrder());
   DateTime jodaDT = new DateTime(dateTime);
   int day = jodaDT.getDayOfYear();
   PDataType returnDataType = getDataType();
   byte[] byteValue = new byte[returnDataType.getByteSize()];
   returnDataType.getCodec().encodeInt(day, byteValue, 0);
   ptr.set(byteValue);
   return true;
 }
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   // This serializes the Map. The format is as follows
   // Map size(VInt ie. 1 to 5 bytes) +
   // ( key length [VInt ie. 1 to 5 bytes] + key bytes + value [VInt ie. 1 to 5 bytes] )*
   buffer = new byte[countMapSerializationSize()];
   int offset = 0;
   offset += ByteUtil.vintToBytes(buffer, offset, this.valueVsCount.size());
   for (Entry<ImmutableBytesPtr, Integer> entry : this.valueVsCount.entrySet()) {
     ImmutableBytesPtr key = entry.getKey();
     offset += ByteUtil.vintToBytes(buffer, offset, key.getLength());
     System.arraycopy(key.get(), key.getOffset(), buffer, offset, key.getLength());
     offset += key.getLength();
     offset += ByteUtil.vintToBytes(buffer, offset, entry.getValue().intValue());
   }
   ptr.set(buffer, 0, offset);
   return true;
 }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    // Reset buffer so that it gets initialized with the current datatype of the column
    buffer = null;
    if (cachedResult == null) {
      columnExp = (ColumnExpression) exps.get(0);
      // Second exp will be a LiteralExpression of Boolean type indicating
      // whether the ordering to be ASC/DESC
      LiteralExpression isAscendingExpression = (LiteralExpression) exps.get(1);
      boolean isAscending = (Boolean) isAscendingExpression.getValue();

      // Third expression will be LiteralExpression
      LiteralExpression percentileExp = (LiteralExpression) exps.get(2);
      float p = ((Number) percentileExp.getValue()).floatValue();
      Map<Object, Integer> sorted = getSortedValueVsCount(isAscending, columnExp.getDataType());
      int currValue = 0;
      Object result = null;
      // Here the Percentile_disc returns the cum_dist() that is greater or equal to the
      // Percentile (p) specified in the query.  So the result set will be of that of the
      // datatype of the column being selected
      for (Entry<Object, Integer> entry : sorted.entrySet()) {
        result = entry.getKey();
        Integer value = entry.getValue();
        currValue += value;
        float cum_dist = (float) currValue / (float) totalCount;
        if (cum_dist >= p) {
          break;
        }
      }
      this.cachedResult = result;
    }
    if (buffer == null) {
      // Initialize based on the datatype
      // columnExp cannot be null
      buffer = new byte[columnExp.getDataType().getByteSize()];
    }
    // Copy the result to the buffer.
    System.arraycopy(
        columnExp.getDataType().toBytes(this.cachedResult), 0, buffer, 0, buffer.length);
    ptr.set(buffer);
    return true;
  }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal result = null;
    for (int i = 0; i < children.size(); i++) {
      if (!children.get(i).evaluate(tuple, ptr) || ptr.getLength() == 0) {
        return false;
      }

      PDataType childType = children.get(i).getDataType();
      BigDecimal bd = (BigDecimal) PDataType.DECIMAL.toObject(ptr, childType);

      if (result == null) {
        result = bd;
      } else {
        result = result.divide(bd, PDataType.DEFAULT_MATH_CONTEXT);
      }
    }
    ptr.set(PDataType.DECIMAL.toBytes(result));
    return true;
  }
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    BigDecimal finalResult = BigDecimal.ZERO;

    for (int i = 0; i < children.size(); i++) {
      if (!children.get(i).evaluate(tuple, ptr)) {
        return false;
      }
      if (ptr.getLength() == 0) {
        return true;
      }
      BigDecimal value;
      PDataType type = children.get(i).getDataType();
      ColumnModifier columnModifier = children.get(i).getColumnModifier();
      if (type == PDataType.TIMESTAMP || type == PDataType.UNSIGNED_TIMESTAMP) {
        value = (BigDecimal) (PDataType.DECIMAL.toObject(ptr, type, columnModifier));
      } else if (type.isCoercibleTo(PDataType.DECIMAL)) {
        value =
            (((BigDecimal) PDataType.DECIMAL.toObject(ptr, columnModifier))
                    .multiply(QueryConstants.BD_MILLIS_IN_DAY))
                .setScale(6, RoundingMode.HALF_UP);
      } else if (type.isCoercibleTo(PDataType.DOUBLE)) {
        value =
            ((BigDecimal.valueOf(type.getCodec().decodeDouble(ptr, columnModifier)))
                    .multiply(QueryConstants.BD_MILLIS_IN_DAY))
                .setScale(6, RoundingMode.HALF_UP);
      } else {
        value = BigDecimal.valueOf(type.getCodec().decodeLong(ptr, columnModifier));
      }
      finalResult = finalResult.add(value);
    }
    Timestamp ts = DateUtil.getTimestamp(finalResult);
    byte[] resultPtr = new byte[getDataType().getByteSize()];
    PDataType.TIMESTAMP.toBytes(ts, resultPtr, 0);
    ptr.set(resultPtr);
    return true;
  }
 private static MutationState upsertSelect(
     PhoenixStatement statement,
     TableRef tableRef,
     RowProjector projector,
     ResultIterator iterator,
     int[] columnIndexes,
     int[] pkSlotIndexes)
     throws SQLException {
   try {
     PhoenixConnection connection = statement.getConnection();
     ConnectionQueryServices services = connection.getQueryServices();
     int maxSize =
         services
             .getProps()
             .getInt(
                 QueryServices.MAX_MUTATION_SIZE_ATTRIB,
                 QueryServicesOptions.DEFAULT_MAX_MUTATION_SIZE);
     int batchSize = Math.min(connection.getMutateBatchSize(), maxSize);
     boolean isAutoCommit = connection.getAutoCommit();
     byte[][] values = new byte[columnIndexes.length][];
     int rowCount = 0;
     Map<ImmutableBytesPtr, Map<PColumn, byte[]>> mutation =
         Maps.newHashMapWithExpectedSize(batchSize);
     PTable table = tableRef.getTable();
     ResultSet rs = new PhoenixResultSet(iterator, projector, statement);
     ImmutableBytesWritable ptr = new ImmutableBytesWritable();
     while (rs.next()) {
       for (int i = 0; i < values.length; i++) {
         PColumn column = table.getColumns().get(columnIndexes[i]);
         byte[] bytes = rs.getBytes(i + 1);
         ptr.set(bytes == null ? ByteUtil.EMPTY_BYTE_ARRAY : bytes);
         Object value = rs.getObject(i + 1);
         int rsPrecision = rs.getMetaData().getPrecision(i + 1);
         Integer precision = rsPrecision == 0 ? null : rsPrecision;
         int rsScale = rs.getMetaData().getScale(i + 1);
         Integer scale = rsScale == 0 ? null : rsScale;
         // We are guaranteed that the two column will have compatible types,
         // as we checked that before.
         if (!column
             .getDataType()
             .isSizeCompatible(
                 ptr,
                 value,
                 column.getDataType(),
                 precision,
                 scale,
                 column.getMaxLength(),
                 column.getScale())) {
           throw new SQLExceptionInfo.Builder(SQLExceptionCode.DATA_EXCEEDS_MAX_CAPACITY)
               .setColumnName(column.getName().getString())
               .setMessage("value=" + column.getDataType().toStringLiteral(ptr, null))
               .build()
               .buildException();
         }
         column
             .getDataType()
             .coerceBytes(
                 ptr,
                 value,
                 column.getDataType(),
                 precision,
                 scale,
                 SortOrder.getDefault(),
                 column.getMaxLength(),
                 column.getScale(),
                 column.getSortOrder());
         values[i] = ByteUtil.copyKeyBytesIfNecessary(ptr);
       }
       setValues(values, pkSlotIndexes, columnIndexes, table, mutation);
       rowCount++;
       // Commit a batch if auto commit is true and we're at our batch size
       if (isAutoCommit && rowCount % batchSize == 0) {
         MutationState state = new MutationState(tableRef, mutation, 0, maxSize, connection);
         connection.getMutationState().join(state);
         connection.commit();
         mutation.clear();
       }
     }
     // If auto commit is true, this last batch will be committed upon return
     return new MutationState(
         tableRef, mutation, rowCount / batchSize * batchSize, maxSize, connection);
   } finally {
     iterator.close();
   }
 }
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(
      value = "QBA_QUESTIONABLE_BOOLEAN_ASSIGNMENT",
      justification = "Assignment designed to work this way.")
  private ReturnCode navigate(
      final byte[] currentKey, int offset, int length, Terminate terminate) {
    int nSlots = slots.size();
    // First check to see if we're in-range until we reach our end key
    if (endKeyLength > 0) {
      if (Bytes.compareTo(currentKey, offset, length, endKey, 0, endKeyLength) < 0) {
        return ReturnCode.INCLUDE;
      }

      // If key range of last slot is a single key, we can increment our position
      // since we know we'll be past the current row after including it.
      if (slots.get(nSlots - 1).get(position[nSlots - 1]).isSingleKey()) {
        if (nextPosition(nSlots - 1) < 0) {
          // Current row will be included, but we have no more
          isDone = true;
          return ReturnCode.NEXT_ROW;
        }
      } else {
        // Reset the positions to zero from the next slot after the earliest ranged slot, since the
        // next key could be bigger at this ranged slot, and smaller than the current position of
        // less significant slots.
        int earliestRangeIndex = nSlots - 1;
        for (int i = 0; i < nSlots; i++) {
          if (!slots.get(i).get(position[i]).isSingleKey()) {
            earliestRangeIndex = i;
            break;
          }
        }
        Arrays.fill(position, earliestRangeIndex + 1, position.length, 0);
      }
    }
    endKeyLength = 0;

    // We could have included the previous
    if (isDone) {
      return ReturnCode.NEXT_ROW;
    }

    int i = 0;
    boolean seek = false;
    int earliestRangeIndex = nSlots - 1;
    ptr.set(currentKey, offset, length);
    schema.first(ptr, i, ValueBitSet.EMPTY_VALUE_BITSET);
    while (true) {
      // Increment to the next range while the upper bound of our current slot is less than our
      // current key
      while (position[i] < slots.get(i).size()
          && slots.get(i).get(position[i]).compareUpperToLowerBound(ptr) < 0) {
        position[i]++;
      }
      Arrays.fill(position, i + 1, position.length, 0);
      if (position[i] >= slots.get(i).size()) {
        // Our current key is bigger than the last range of the current slot.
        // If navigating after current key, backtrack and increment the key of the previous slot
        // values.
        // If navigating to current key, just return
        if (terminate == Terminate.AT) {
          return ReturnCode.SEEK_NEXT_USING_HINT;
        }
        if (i == 0) {
          isDone = true;
          return ReturnCode.NEXT_ROW;
        }
        // Increment key and backtrack until in range. We know at this point that we'll be
        // issuing a seek next hint.
        seek = true;
        Arrays.fill(position, i, position.length, 0);
        i--;
        // If we're positioned at a single key, no need to copy the current key and get the next key
        // .
        // Instead, just increment to the next key and continue.
        boolean incremented = false;
        while (i >= 0
            && slots.get(i).get(position[i]).isSingleKey()
            && (incremented = true)
            && (position[i] = (position[i] + 1) % slots.get(i).size()) == 0) {
          i--;
          incremented = false;
        }
        if (i < 0) {
          isDone = true;
          return ReturnCode.NEXT_ROW;
        }
        if (incremented) {
          // Continue the loop after setting the start key, because our start key maybe smaller than
          // the current key, so we'll end up incrementing the start key until it's bigger than the
          // current key.
          setStartKey();
          ptr.set(ptr.get(), offset, length);
          // Reinitialize iterator to be positioned at previous slot position
          schema.setAccessor(ptr, i, ValueBitSet.EMPTY_VALUE_BITSET);
        } else {
          int currentLength = setStartKey(ptr, offset, i + 1);
          // From here on, we use startKey as our buffer with offset reset to 0
          // We've copied the part of the current key above that we need into startKey
          ptr.set(startKey, offset = 0, length = startKeyLength);
          // Reinitialize iterator to be positioned at previous slot position
          // TODO: a schema.previous would potentially be more efficient
          schema.setAccessor(ptr, i, ValueBitSet.EMPTY_VALUE_BITSET);
          // Do nextKey after setting the accessor b/c otherwise the null byte may have
          // been incremented causing us not to find it
          ByteUtil.nextKey(startKey, currentLength);
        }
      } else if (slots.get(i).get(position[i]).compareLowerToUpperBound(ptr) > 0) {
        // Our current key is less than the lower range of the current position in the current slot.
        // Seek to the lower range, since it's bigger than the current key
        setStartKey(ptr, offset, i);
        return ReturnCode.SEEK_NEXT_USING_HINT;
      } else { // We're in range, check the next slot
        if (!slots.get(i).get(position[i]).isSingleKey() && i < earliestRangeIndex) {
          earliestRangeIndex = i;
        }
        i++;
        // If we're past the last slot or we know we're seeking to the next (in
        // which case the previously updated slot was verified to be within the
        // range, so we don't need to check the rest of the slots. If we were
        // to check the rest of the slots, we'd get into trouble because we may
        // have a null byte that was incremented which screws up our schema.next call)
        if (i >= nSlots || seek) {
          break;
        }
        // If we run out of slots in our key, it means we have a partial key. In this
        // case, we seek to the next full key after this one.
        // TODO: test for this
        if (schema.next(ptr, i, offset + length, ValueBitSet.EMPTY_VALUE_BITSET) == null) {
          setStartKey(ptr, offset, i);
          return ReturnCode.SEEK_NEXT_USING_HINT;
        }
      }
    }

    if (seek) {
      return ReturnCode.SEEK_NEXT_USING_HINT;
    }
    // Else, we're in range for all slots and can include this row plus all rows
    // up to the upper range of our last slot. We do this for ranges and single keys
    // since we potentially have multiple key values for the same row key.
    setEndKey(ptr, offset, slots.size() - 1);
    return ReturnCode.INCLUDE;
  }
 private boolean intersect(
     byte[] lowerInclusiveKey, byte[] upperExclusiveKey, List<List<KeyRange>> newSlots) {
   boolean lowerUnbound = (lowerInclusiveKey.length == 0);
   Arrays.fill(position, 0);
   isDone = false;
   int startPos = 0;
   int lastSlot = slots.size() - 1;
   if (!lowerUnbound) {
     // Find the position of the first slot of the lower range
     ptr.set(lowerInclusiveKey);
     schema.first(ptr, 0, ValueBitSet.EMPTY_VALUE_BITSET);
     startPos = ScanUtil.searchClosestKeyRangeWithUpperHigherThanPtr(slots.get(0), ptr, 0);
     // Lower range is past last upper range of first slot, so cannot possibly be in range
     if (startPos >= slots.get(0).size()) {
       return false;
     }
   }
   boolean upperUnbound = (upperExclusiveKey.length == 0);
   int endPos = slots.get(0).size() - 1;
   if (!upperUnbound) {
     // Find the position of the first slot of the upper range
     ptr.set(upperExclusiveKey);
     schema.first(ptr, 0, ValueBitSet.EMPTY_VALUE_BITSET);
     endPos = ScanUtil.searchClosestKeyRangeWithUpperHigherThanPtr(slots.get(0), ptr, startPos);
     // Upper range lower than first lower range of first slot, so cannot possibly be in range
     if (endPos == 0
         && Bytes.compareTo(upperExclusiveKey, slots.get(0).get(0).getLowerRange()) <= 0) {
       return false;
     }
     // Past last position, so we can include everything from the start position
     if (endPos >= slots.get(0).size()) {
       upperUnbound = true;
       endPos = slots.get(0).size() - 1;
     }
   }
   if (!lowerUnbound) {
     position[0] = startPos;
     navigate(lowerInclusiveKey, 0, lowerInclusiveKey.length, Terminate.AFTER);
     if (filterAllRemaining()) {
       return false;
     }
   }
   if (upperUnbound) {
     if (newSlots != null) {
       newSlots.add(slots.get(0).subList(startPos, endPos + 1));
       newSlots.addAll(slots.subList(1, slots.size()));
     }
     return true;
   }
   int[] lowerPosition = Arrays.copyOf(position, position.length);
   // Navigate to the upperExclusiveKey, but not past it
   ReturnCode endCode = navigate(upperExclusiveKey, 0, upperExclusiveKey.length, Terminate.AT);
   if (endCode == ReturnCode.INCLUDE) {
     setStartKey();
     // If the upperExclusiveKey is equal to the start key, we've gone one position too far, since
     // our upper key is exclusive. In that case, go to the previous key
     if (Bytes.compareTo(
                 startKey, 0, startKeyLength, upperExclusiveKey, 0, upperExclusiveKey.length)
             == 0
         && (previousPosition(lastSlot) < 0 || position[0] < lowerPosition[0])) {
       // If by backing up one position we have an empty range, then return
       return false;
     }
   } else if (endCode == ReturnCode.SEEK_NEXT_USING_HINT) {
     // The upperExclusive key is smaller than the slots stored in the position. Check if it's the
     // same position
     // as the slots for lowerInclusive. If so, there is no intersection.
     if (Arrays.equals(lowerPosition, position)) {
       return false;
     }
   }
   // Copy inclusive all positions
   for (int i = 0; i <= lastSlot; i++) {
     List<KeyRange> newRanges =
         slots.get(i).subList(lowerPosition[i], Math.min(position[i] + 1, slots.get(i).size()));
     if (newRanges.isEmpty()) {
       return false;
     }
     if (newSlots != null) {
       newSlots.add(newRanges);
     }
     if (position[i] > lowerPosition[i]) {
       if (newSlots != null) {
         newSlots.addAll(slots.subList(i + 1, slots.size()));
       }
       break;
     }
   }
   return true;
 }
Beispiel #19
0
 @Override
 public boolean getValue(byte[] family, byte[] qualifier, ImmutableBytesWritable ptr) {
   ptr.set(projectedValue);
   return true;
 }
Beispiel #20
0
 @Override
 public void getKey(ImmutableBytesWritable ptr) {
   ptr.set(keyPtr.get(), keyPtr.getOffset(), keyPtr.getLength());
 }
Beispiel #21
0
 @Override
 public int newKey(ImmutableBytesWritable key, byte[][] values) {
   int i = 0;
   TrustedByteArrayOutputStream os =
       new TrustedByteArrayOutputStream(SchemaUtil.estimateKeyLength(this));
   try {
     List<PColumn> columns = getPKColumns();
     int nColumns = columns.size();
     PColumn lastPKColumn = columns.get(nColumns - 1);
     while (i < values.length && i < nColumns) {
       PColumn column = columns.get(i);
       PDataType type = column.getDataType();
       // This will throw if the value is null and the type doesn't allow null
       byte[] byteValue = values[i++];
       if (byteValue == null) {
         byteValue = ByteUtil.EMPTY_BYTE_ARRAY;
       }
       // An empty byte array return value means null. Do this,
       // since a type may have muliple representations of null.
       // For example, VARCHAR treats both null and an empty string
       // as null. This way we don't need to leak that part of the
       // implementation outside of PDataType by checking the value
       // here.
       if (byteValue.length == 0 && !column.isNullable()) {
         throw new ConstraintViolationException(
             name.getString() + "." + column.getName().getString() + " may not be null");
       }
       Integer byteSize = column.getByteSize();
       if (type.isFixedWidth()) { // TODO: handle multi-byte characters
         if (byteValue.length != byteSize) {
           throw new ConstraintViolationException(
               name.getString()
                   + "."
                   + column.getName().getString()
                   + " must be "
                   + byteSize
                   + " bytes ("
                   + SchemaUtil.toString(type, byteValue)
                   + ")");
         }
       } else if (byteSize != null && byteValue.length > byteSize) {
         throw new ConstraintViolationException(
             name.getString()
                 + "."
                 + column.getName().getString()
                 + " may not exceed "
                 + byteSize
                 + " bytes ("
                 + SchemaUtil.toString(type, byteValue)
                 + ")");
       }
       os.write(byteValue, 0, byteValue.length);
       // Separate variable length column values in key with zero byte
       if (!type.isFixedWidth() && column != lastPKColumn) {
         os.write(SEPARATOR_BYTE);
       }
     }
     // If some non null pk values aren't set, then throw
     if (i < nColumns) {
       PColumn column = columns.get(i);
       PDataType type = column.getDataType();
       if (type.isFixedWidth() || !column.isNullable()) {
         throw new ConstraintViolationException(
             name.getString() + "." + column.getName().getString() + " may not be null");
       }
       // Separate variable length column values in key with zero byte
       if (column != lastPKColumn) {
         os.write(SEPARATOR_BYTE);
       }
     }
     key.set(os.getBuffer(), 0, os.size());
     return i;
   } finally {
     try {
       os.close();
     } catch (IOException e) {
       throw new RuntimeException(e); // Impossible
     }
   }
 }
Beispiel #22
0
 @Override
 public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
   // Literal always evaluates, even when it returns null
   ptr.set(byteValue);
   return true;
 }