Пример #1
0
 public Builder add(Slice slice) {
   assert comparator.compare(slice.start(), slice.end()) <= 0;
   if (slices.size() > 0
       && comparator.compare(slices.get(slices.size() - 1).end(), slice.start()) > 0)
     needsNormalizing = true;
   slices.add(slice);
   return this;
 }
Пример #2
0
    public Slices build() {
      if (slices.isEmpty()) return NONE;

      if (slices.size() == 1 && slices.get(0) == Slice.ALL) return ALL;

      List<Slice> normalized = needsNormalizing ? normalize(slices) : slices;

      return new ArrayBackedSlices(comparator, normalized.toArray(new Slice[normalized.size()]));
    }
Пример #3
0
    /**
     * Given an array of slices (potentially overlapping and in any order) and return an equivalent
     * array of non-overlapping slices in clustering order.
     *
     * @param slices an array of slices. This may be modified by this method.
     * @return the smallest possible array of non-overlapping slices in clustering order. If the
     *     original slices are already non-overlapping and in comparator order, this may or may not
     *     return the provided slices directly.
     */
    private List<Slice> normalize(List<Slice> slices) {
      if (slices.size() <= 1) return slices;

      Collections.sort(
          slices,
          new Comparator<Slice>() {
            @Override
            public int compare(Slice s1, Slice s2) {
              int c = comparator.compare(s1.start(), s2.start());
              if (c != 0) return c;

              return comparator.compare(s1.end(), s2.end());
            }
          });

      List<Slice> slicesCopy = new ArrayList<>(slices.size());

      Slice last = slices.get(0);

      for (int i = 1; i < slices.size(); i++) {
        Slice s2 = slices.get(i);

        boolean includesStart = last.includes(comparator, s2.start());
        boolean includesFinish = last.includes(comparator, s2.end());

        if (includesStart && includesFinish) continue;

        if (!includesStart && !includesFinish) {
          slicesCopy.add(last);
          last = s2;
          continue;
        }

        if (includesStart) {
          last = Slice.make(last.start(), s2.end());
          continue;
        }

        assert !includesFinish;
      }

      slicesCopy.add(last);
      return slicesCopy;
    }
Пример #4
0
    public String toCQLString(CFMetaData metadata) {
      StringBuilder sb = new StringBuilder();

      // In CQL, condition are expressed by column, so first group things that way,
      // i.e. for each column, we create a list of what each slice contains on that column
      int clusteringSize = metadata.clusteringColumns().size();
      List<List<ComponentOfSlice>> columnComponents = new ArrayList<>(clusteringSize);
      for (int i = 0; i < clusteringSize; i++) {
        List<ComponentOfSlice> perSlice = new ArrayList<>();
        columnComponents.add(perSlice);

        for (int j = 0; j < slices.length; j++) {
          ComponentOfSlice c = ComponentOfSlice.fromSlice(i, slices[j]);
          if (c != null) perSlice.add(c);
        }
      }

      boolean needAnd = false;
      for (int i = 0; i < clusteringSize; i++) {
        ColumnDefinition column = metadata.clusteringColumns().get(i);
        List<ComponentOfSlice> componentInfo = columnComponents.get(i);
        if (componentInfo.isEmpty()) break;

        // For a given column, there is only 3 cases that CQL currently generates:
        //   1) every slice are EQ with the same value, it's a simple '=' relation.
        //   2) every slice are EQ but with different values, it's a IN relation.
        //   3) every slice aren't EQ but have the same values, we have inequality relations.
        // Note that this doesn't cover everything that ReadCommand can express, but
        // as it's all that CQL support for now, we'll ignore other cases (which would then
        // display a bogus query but that's not the end of the world).
        // TODO: we should improve this at some point.
        ComponentOfSlice first = componentInfo.get(0);
        if (first.isEQ()) {
          if (needAnd) sb.append(" AND ");
          needAnd = true;

          sb.append(column.name);

          Set<ByteBuffer> values = new LinkedHashSet<>();
          for (int j = 0; j < componentInfo.size(); j++)
            values.add(componentInfo.get(j).startValue);

          if (values.size() == 1) {
            sb.append(" = ").append(column.type.getString(first.startValue));
          } else {
            sb.append(" IN (");
            int j = 0;
            for (ByteBuffer value : values)
              sb.append(j++ == 0 ? "" : ", ").append(column.type.getString(value));
            sb.append(")");
          }
        } else {
          // As said above, we assume (without checking) that this means all ComponentOfSlice for
          // this column
          // are the same, so we only bother about the first.
          if (first.startValue != null) {
            if (needAnd) sb.append(" AND ");
            needAnd = true;
            sb.append(column.name)
                .append(first.startInclusive ? " >= " : " > ")
                .append(column.type.getString(first.startValue));
          }
          if (first.endValue != null) {
            if (needAnd) sb.append(" AND ");
            needAnd = true;
            sb.append(column.name)
                .append(first.endInclusive ? " <= " : " < ")
                .append(column.type.getString(first.endValue));
          }
        }
      }
      return sb.toString();
    }
Пример #5
0
 public int size() {
   return slices.size();
 }