private static ColumnIdentifier getKeyId(CFMetaData cfm, int i) {
   List<ByteBuffer> definedNames = cfm.getKeyAliases();
   // For compatibility sake, non-composite key default alias is 'key', not 'key1'.
   return definedNames == null || i >= definedNames.size() || cfm.getKeyAliases().get(i) == null
       ? new ColumnIdentifier(i == 0 ? DEFAULT_KEY_ALIAS : DEFAULT_KEY_ALIAS + (i + 1), false)
       : new ColumnIdentifier(cfm.getKeyAliases().get(i), definitionType);
 }
  private int discardHead(
      ColumnFamily cf,
      int toDiscard,
      ColumnFamily copy,
      Iterator<Column> iter,
      DeletionInfo.InOrderTester tester) {
    ColumnCounter counter = columnCounter();

    List<Column> staticColumns = new ArrayList<>(cfm.staticColumns().size());

    // Discard the first 'toDiscard' live, non-static columns
    while (iter.hasNext()) {
      Column c = iter.next();

      // if it's a static column, don't count it and save it to add to the trimmed results
      ColumnDefinition columnDef = cfm.getColumnDefinitionFromColumnName(c.name());
      if (columnDef != null && columnDef.type == ColumnDefinition.Type.STATIC) {
        staticColumns.add(c);
        continue;
      }

      counter.count(c, tester);

      // once we've discarded the required amount, add the rest
      if (counter.live() > toDiscard) {
        for (Column staticColumn : staticColumns) copy.addColumn(staticColumn);

        copy.addColumn(c);
        while (iter.hasNext()) copy.addColumn(iter.next());
      }
    }
    return Math.min(counter.live(), toDiscard);
  }
  public boolean announceMigration(boolean isLocalOnly) throws RequestValidationException {
    CFMetaData cfm = Schema.instance.getCFMetaData(keyspace(), columnFamily()).copy();
    IndexTarget target = rawTarget.prepare(cfm);
    logger.debug("Updating column {} definition for index {}", target.column, indexName);
    ColumnDefinition cd = cfm.getColumnDefinition(target.column);

    if (cd.getIndexType() != null && ifNotExists) return false;

    if (properties.isCustom) {
      cd.setIndexType(IndexType.CUSTOM, properties.getOptions());
    } else if (cfm.comparator.isCompound()) {
      Map<String, String> options = Collections.emptyMap();
      // For now, we only allow indexing values for collections, but we could later allow
      // to also index map keys, so we record that this is the values we index to make our
      // lives easier then.
      if (cd.type.isCollection() && cd.type.isMultiCell())
        options =
            ImmutableMap.of(
                target.isCollectionKeys
                    ? SecondaryIndex.INDEX_KEYS_OPTION_NAME
                    : SecondaryIndex.INDEX_VALUES_OPTION_NAME,
                "");
      cd.setIndexType(IndexType.COMPOSITES, options);
    } else {
      cd.setIndexType(IndexType.KEYS, Collections.<String, String>emptyMap());
    }

    cd.setIndexName(indexName);
    cfm.addDefaultIndexNames();
    MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
    return true;
  }
 private static CFMetaData newCFMetaData(String ksname, String cfname) {
   CFMetaData metadata =
       CFMetaData.Builder.create(ksname, cfname)
           .addPartitionKey("key", UTF8Type.instance)
           .addClusteringColumn("col", UTF8Type.instance)
           .addRegularColumn("value", UTF8Type.instance)
           .withPartitioner(Murmur3Partitioner.instance)
           .build();
   metadata.caching(CachingParams.CACHE_NOTHING);
   return metadata;
 }
 /**
  * Returns the first non-static cell in the ColumnFamily. This is necessary to avoid recording a
  * static column as the "last" cell seen in a reversed query. Because we will always query static
  * columns alongside the normal data for a page, they are not a good indicator of where paging
  * should resume. When we begin the next page, we need to start from the last non-static cell.
  */
 protected Column firstNonStaticColumn(ColumnFamily cf) {
   for (Column column : cf) {
     ColumnDefinition def = cfm.getColumnDefinitionFromColumnName(column.name());
     if (def == null || def.type != ColumnDefinition.Type.STATIC) return column;
   }
   return null;
 }
  public static CFMetaData initializeCfMetaData(Configuration configuration) {
    final String cql = configuration.get(Aegisthus.Feature.CONF_CQL_SCHEMA);
    Preconditions.checkNotNull(cql, "Cannot proceed without CQL definition.");

    final CreateTableStatement statement = getCreateTableStatement(cql);

    try {
      final CFMetaData cfMetaData = statement.getCFMetaData();
      cfMetaData.rebuild();

      return cfMetaData;
    } catch (RequestValidationException e) {
      // Cannot proceed if an error occurs
      throw new RuntimeException("Error initializing CFMetadata from CQL.", e);
    }
  }
 // ONLY to be used for testing, to create a mock Memtable
 @VisibleForTesting
 public Memtable(CFMetaData metadata) {
   this.initialComparator = metadata.comparator;
   this.cfs = null;
   this.allocator = null;
   this.columnsCollector = new ColumnsCollector(metadata.partitionColumns());
 }
  public RowMutation mutationForKey(
      ByteBuffer key,
      String keyspace,
      Long timestamp,
      ThriftClientState clientState,
      List<ByteBuffer> variables,
      CFMetaData metadata)
      throws InvalidRequestException {
    RowMutation rm = new RowMutation(keyspace, key);

    QueryProcessor.validateKeyAlias(metadata, keyName);

    AbstractType<?> comparator = metadata.getComparatorFor(null);

    if (columns.size() < 1) {
      // No columns, delete the row
      rm.delete(
          new QueryPath(columnFamily), (timestamp == null) ? getTimestamp(clientState) : timestamp);
    } else {
      // Delete specific columns
      for (Term column : columns) {
        ByteBuffer columnName = column.getByteBuffer(comparator, variables);
        validateColumnName(columnName);
        rm.delete(
            new QueryPath(columnFamily, null, columnName),
            (timestamp == null) ? getTimestamp(clientState) : timestamp);
      }
    }

    return rm;
  }
 public static CompositeType buildIndexComparator(
     CFMetaData baseMetadata, ColumnDefinition columnDef) {
   int ckCount = baseMetadata.clusteringKeyColumns().size();
   List<AbstractType<?>> types = new ArrayList<AbstractType<?>>(ckCount + 1);
   types.add(SecondaryIndex.keyComparator);
   types.addAll(baseMetadata.comparator.getComponents());
   return CompositeType.getInstance(types);
 }
  public void applyPropertiesTo(CFMetaData cfmd) throws RequestValidationException {
    cfmd.defaultValidator(defaultValidator)
        .keyValidator(keyValidator)
        .columnMetadata(getColumns())
        .setDense(isDense);

    cfmd.addColumnMetadataFromAliases(
        keyAliases, keyValidator, ColumnDefinition.Type.PARTITION_KEY);
    cfmd.addColumnMetadataFromAliases(
        columnAliases, comparator, ColumnDefinition.Type.CLUSTERING_KEY);
    if (valueAlias != null)
      cfmd.addColumnMetadataFromAliases(
          Collections.<ByteBuffer>singletonList(valueAlias),
          defaultValidator,
          ColumnDefinition.Type.COMPACT_VALUE);

    properties.applyToCFMetadata(cfmd);
  }
 private static Name createValue(CFMetaData cfm) {
   ColumnIdentifier alias = getValueId(cfm);
   // That's how we distinguish between 'no value alias because coming from thrift' and 'I
   // explicitely did not
   // define a value' (see CreateColumnFamilyStatement)
   return alias.key.equals(ByteBufferUtil.EMPTY_BYTE_BUFFER)
       ? null
       : new Name(cfm.ksName, cfm.cfName, alias, Name.Kind.VALUE_ALIAS, cfm.getDefaultValidator());
 }
  public ParsedStatement.Prepared prepare(ColumnSpecification[] boundNames)
      throws InvalidRequestException {
    CFMetaData metadata = ThriftValidation.validateColumnFamily(keyspace(), columnFamily());
    type = metadata.getDefaultValidator().isCommutative() ? Type.COUNTER : Type.LOGGED;

    cfDef = metadata.getCfDef();
    UpdateStatement.processKeys(cfDef, whereClause, processedKeys, boundNames);

    for (Selector column : columns) {
      CFDefinition.Name name = cfDef.get(column.id());
      if (name == null)
        throw new InvalidRequestException(String.format("Unknown identifier %s", column));

      // For compact, we only have one value except the key, so the only form of DELETE that make
      // sense is without a column
      // list. However, we support having the value name for coherence with the static/sparse case
      if (name.kind != CFDefinition.Name.Kind.COLUMN_METADATA
          && name.kind != CFDefinition.Name.Kind.VALUE_ALIAS)
        throw new InvalidRequestException(
            String.format(
                "Invalid identifier %s for deletion (should not be a PRIMARY KEY part)", column));

      if (column.key() != null) {
        if (name.type instanceof ListType) {
          if (column.key().isBindMarker())
            boundNames[column.key().bindIndex] = ListOperation.indexSpecOf(name);
        } else if (name.type instanceof MapType) {
          if (column.key().isBindMarker())
            boundNames[column.key().bindIndex] = MapOperation.keySpecOf(name, (MapType) name.type);
        } else {
          throw new InvalidRequestException(
              String.format(
                  "Invalid selection %s since %s is neither a list or a map", column, column.id()));
        }
      }

      toRemove.add(Pair.create(name, column.key()));
    }

    return new ParsedStatement.Prepared(this, Arrays.<ColumnSpecification>asList(boundNames));
  }
 /**
  * Create a new buffering writer.
  *
  * @param directory the directory where to write the sstables
  * @param partitioner the partitioner
  * @param keyspace the keyspace name
  * @param columnFamily the column family name
  * @param comparator the column family comparator
  * @param subComparator the column family subComparator or null if not a Super column family.
  * @param bufferSizeInMB the data size in MB before which a sstable is written and the buffer
  *     reseted. This correspond roughly to the written data size (i.e. the size of the create
  *     sstable). The actual size used in memory will be higher (by how much depends on the size of
  *     the columns you add). For 1GB of heap, a 128 bufferSizeInMB is probably a reasonable
  *     choice. If you experience OOM, this value should be lowered.
  */
 public SSTableSimpleUnsortedWriter(
     File directory,
     IPartitioner partitioner,
     String keyspace,
     String columnFamily,
     AbstractType<?> comparator,
     AbstractType<?> subComparator,
     int bufferSizeInMB,
     CompressionParameters compressParameters) {
   this(
       directory,
       CFMetaData.denseCFMetaData(keyspace, columnFamily, comparator, subComparator)
           .compressionParameters(compressParameters),
       partitioner,
       bufferSizeInMB);
 }
    @Override
    public void init(String keyspace) {
      Iterator<InetAddress> hostiter = hosts.iterator();
      while (hostiter.hasNext()) {
        try {
          // Query endpoint to ranges map and schemas from thrift
          InetAddress host = hostiter.next();
          Cassandra.Client client =
              createThriftClient(
                  host.getHostAddress(), rpcPort, this.user, this.passwd, this.transportFactory);

          setPartitioner(client.describe_partitioner());
          Token.TokenFactory tkFactory = getPartitioner().getTokenFactory();

          for (TokenRange tr : client.describe_ring(keyspace)) {
            Range<Token> range =
                new Range<>(
                    tkFactory.fromString(tr.start_token),
                    tkFactory.fromString(tr.end_token),
                    getPartitioner());
            for (String ep : tr.endpoints) {
              addRangeForEndpoint(range, InetAddress.getByName(ep));
            }
          }

          String query =
              String.format(
                  "SELECT * FROM %s.%s WHERE keyspace_name = '%s'",
                  Keyspace.SYSTEM_KS, SystemKeyspace.SCHEMA_COLUMNFAMILIES_CF, keyspace);
          CqlResult result =
              client.execute_cql3_query(
                  ByteBufferUtil.bytes(query), Compression.NONE, ConsistencyLevel.ONE);
          for (CqlRow row : result.rows) {
            CFMetaData metadata = CFMetaData.fromThriftCqlRow(row);
            knownCfs.put(metadata.cfName, metadata);
          }
          break;
        } catch (Exception e) {
          if (!hostiter.hasNext())
            throw new RuntimeException("Could not retrieve endpoint ranges: ", e);
        }
      }
    }
Beispiel #15
0
  @Override
  public void applyModels() throws IOException {
    KSMetaData ksm = DatabaseDescriptor.getTableDefinition(name);
    // remove the table from the static instances.
    Table table = Table.clear(ksm.name);
    if (table == null) throw new IOException("Table is not active. " + ksm.name);

    // remove all cfs from the table instance.
    for (CFMetaData cfm : ksm.cfMetaData().values()) {
      CFMetaData.purge(cfm);
      table.dropCf(cfm.cfId);
      SystemTable.markForRemoval(cfm);
    }

    // reset defs.
    DatabaseDescriptor.clearTableDefinition(ksm, newVersion);
    CommitLog.instance().forceNewSegment();
    Migration.cleanupDeadFiles(blockOnFileDeletion);

    // clear up any local hinted data for this keyspace.
    HintedHandOffManager.renameHints(name, null);
  }
  public void applyModels() throws IOException {
    ColumnFamilyStore cfs = Table.open(tableName).getColumnFamilyStore(cfName);

    // reinitialize the table.
    KSMetaData existing = DatabaseDescriptor.getTableDefinition(tableName);
    CFMetaData cfm = existing.cfMetaData().get(cfName);
    KSMetaData ksm = makeNewKeyspaceDefinition(existing);
    CFMetaData.purge(cfm);
    DatabaseDescriptor.setTableDefinition(ksm, newVersion);

    if (!clientMode) {
      cfs.snapshot(Table.getTimestampedSnapshotName(null));

      CompactionManager.instance.getCompactionLock().lock();
      cfs.flushLock.lock();
      try {
        Table.open(ksm.name).dropCf(cfm.cfId);
      } finally {
        cfs.flushLock.unlock();
        CompactionManager.instance.getCompactionLock().unlock();
      }
    }
  }
  public static Message createMessage(
      String keyspace, byte[] key, String columnFamily, List<ColumnFamily> columnFamilies) {
    ColumnFamily baseColumnFamily;
    DataOutputBuffer bufOut = new DataOutputBuffer();
    RowMutation rm;
    Message message;
    Column column;

    /* Get the first column family from list, this is just to get past validation */
    baseColumnFamily =
        new ColumnFamily(
            ColumnFamilyType.Standard,
            DatabaseDescriptor.getComparator(keyspace, columnFamily),
            DatabaseDescriptor.getSubComparator(keyspace, columnFamily),
            CFMetaData.getId(keyspace, columnFamily));

    for (ColumnFamily cf : columnFamilies) {
      bufOut.reset();
      ColumnFamily.serializer().serializeWithIndexes(cf, bufOut);
      byte[] data = new byte[bufOut.getLength()];
      System.arraycopy(bufOut.getData(), 0, data, 0, bufOut.getLength());

      column = new Column(FBUtilities.toByteBuffer(cf.id()), ByteBuffer.wrap(data), 0);
      baseColumnFamily.addColumn(column);
    }
    rm = new RowMutation(keyspace, ByteBuffer.wrap(key));
    rm.add(baseColumnFamily);

    try {
      /* Make message */
      message = rm.makeRowMutationMessage(StorageService.Verb.BINARY, MessagingService.version_);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    return message;
  }
 public ColumnNameBuilder getKeyNameBuilder() {
   return hasCompositeKey
       ? new CompositeType.Builder((CompositeType) cfm.getKeyValidator())
       : new NonCompositeBuilder(cfm.getKeyValidator());
 }
 /**
  * Creates a new <code>TokenRestriction</code> that apply to the specified columns.
  *
  * @param columnDefs the definition of the columns to which apply the token restriction
  */
 public TokenRestriction(CFMetaData metadata, List<ColumnDefinition> columnDefs) {
   super(metadata.getKeyValidatorAsClusteringComparator());
   this.columnDefs = columnDefs;
   this.metadata = metadata;
 }
 private static ColumnIdentifier getValueId(CFMetaData cfm) {
   return cfm.getValueAlias() == null
       ? new ColumnIdentifier(DEFAULT_VALUE_ALIAS, false)
       : new ColumnIdentifier(cfm.getValueAlias(), definitionType);
 }
 private static ColumnIdentifier getColumnId(CFMetaData cfm, int i) {
   List<ByteBuffer> definedNames = cfm.getColumnAliases();
   return definedNames == null || i >= definedNames.size() || cfm.getColumnAliases().get(i) == null
       ? new ColumnIdentifier(DEFAULT_COLUMN_ALIAS + (i + 1), false)
       : new ColumnIdentifier(cfm.getColumnAliases().get(i), definitionType);
 }
  public void announceMigration() throws RequestValidationException {
    CFMetaData meta = validateColumnFamily(keyspace(), columnFamily());
    CFMetaData cfm = meta.clone();

    CFDefinition cfDef = meta.getCfDef();
    CFDefinition.Name name = columnName == null ? null : cfDef.get(columnName);
    switch (oType) {
      case ADD:
        if (cfDef.isCompact)
          throw new InvalidRequestException("Cannot add new column to a compact CF");
        if (name != null) {
          switch (name.kind) {
            case KEY_ALIAS:
            case COLUMN_ALIAS:
              throw new InvalidRequestException(
                  String.format(
                      "Invalid column name %s because it conflicts with a PRIMARY KEY part",
                      columnName));
            case COLUMN_METADATA:
              throw new InvalidRequestException(
                  String.format(
                      "Invalid column name %s because it conflicts with an existing column",
                      columnName));
          }
        }

        AbstractType<?> type = validator.getType();
        if (type instanceof CollectionType) {
          if (!cfDef.isComposite)
            throw new InvalidRequestException(
                "Cannot use collection types with non-composite PRIMARY KEY");
          if (cfDef.cfm.isSuper())
            throw new InvalidRequestException(
                "Cannot use collection types with Super column family");

          Map<ByteBuffer, CollectionType> collections =
              cfDef.hasCollections
                  ? new HashMap<ByteBuffer, CollectionType>(cfDef.getCollectionType().defined)
                  : new HashMap<ByteBuffer, CollectionType>();

          collections.put(columnName.key, (CollectionType) type);
          ColumnToCollectionType newColType = ColumnToCollectionType.getInstance(collections);
          List<AbstractType<?>> ctypes =
              new ArrayList<AbstractType<?>>(((CompositeType) cfm.comparator).types);
          if (cfDef.hasCollections) ctypes.set(ctypes.size() - 1, newColType);
          else ctypes.add(newColType);
          cfm.comparator = CompositeType.getInstance(ctypes);
        }

        Integer componentIndex =
            cfDef.isComposite
                ? ((CompositeType) meta.comparator).types.size() - (cfDef.hasCollections ? 2 : 1)
                : null;
        cfm.addColumnDefinition(ColumnDefinition.regularDef(columnName.key, type, componentIndex));
        break;

      case ALTER:
        if (name == null)
          throw new InvalidRequestException(
              String.format("Column %s was not found in table %s", columnName, columnFamily()));

        switch (name.kind) {
          case KEY_ALIAS:
            AbstractType<?> newType = validator.getType();
            if (newType instanceof CounterColumnType)
              throw new InvalidRequestException(
                  String.format(
                      "counter type is not supported for PRIMARY KEY part %s", columnName));
            if (cfDef.hasCompositeKey) {
              List<AbstractType<?>> newTypes =
                  new ArrayList<AbstractType<?>>(((CompositeType) cfm.getKeyValidator()).types);
              newTypes.set(name.position, newType);
              cfm.keyValidator(CompositeType.getInstance(newTypes));
            } else {
              cfm.keyValidator(newType);
            }
            break;
          case COLUMN_ALIAS:
            assert cfDef.isComposite;
            List<AbstractType<?>> newTypes =
                new ArrayList<AbstractType<?>>(((CompositeType) cfm.comparator).types);
            newTypes.set(name.position, validator.getType());
            cfm.comparator = CompositeType.getInstance(newTypes);
            break;
          case VALUE_ALIAS:
            cfm.defaultValidator(validator.getType());
            break;
          case COLUMN_METADATA:
            ColumnDefinition column = cfm.getColumnDefinition(columnName.key);
            column.setValidator(validator.getType());
            break;
        }
        break;

      case DROP:
        if (cfDef.isCompact)
          throw new InvalidRequestException("Cannot drop columns from a compact CF");
        if (name == null)
          throw new InvalidRequestException(
              String.format("Column %s was not found in table %s", columnName, columnFamily()));

        switch (name.kind) {
          case KEY_ALIAS:
          case COLUMN_ALIAS:
            throw new InvalidRequestException(
                String.format("Cannot drop PRIMARY KEY part %s", columnName));
          case COLUMN_METADATA:
            ColumnDefinition toDelete = null;
            for (ColumnDefinition columnDef : cfm.regularColumns()) {
              if (columnDef.name.equals(columnName.key)) toDelete = columnDef;
            }
            assert toDelete != null;
            cfm.removeColumnDefinition(toDelete);
            break;
        }
        break;
      case OPTS:
        if (cfProps == null)
          throw new InvalidRequestException(
              String.format("ALTER COLUMNFAMILY WITH invoked, but no parameters found"));

        cfProps.validate();
        cfProps.applyToCFMetadata(cfm);
        break;
      case RENAME:
        for (Map.Entry<ColumnIdentifier, ColumnIdentifier> entry : renames.entrySet()) {
          ColumnIdentifier from = entry.getKey();
          ColumnIdentifier to = entry.getValue();
          cfm.renameColumn(from.key, from.toString(), to.key, to.toString());
        }
        break;
    }

    MigrationManager.announceColumnFamilyUpdate(cfm, false);
  }
Beispiel #23
0
  public void validate() throws InvalidRequestException, ConfigurationException {
    compactionStrategyClass = CFMetaData.DEFAULT_COMPACTION_STRATEGY_CLASS;

    // we need to remove parent:key = value pairs from the main properties
    Set<String> propsToRemove = new HashSet<String>();

    // check if we have compaction/compression options
    for (String property : properties.keySet()) {
      if (!property.contains(":")) continue;

      String key = property.split(":")[1];
      String val = properties.get(property);

      if (property.startsWith(COMPACTION_OPTIONS_PREFIX)) {
        compactionStrategyOptions.put(key, val);
        propsToRemove.add(property);
      }

      if (property.startsWith(COMPRESSION_PARAMETERS_PREFIX)) {
        compressionParameters.put(key, val);
        propsToRemove.add(property);
      }
    }

    for (String property : propsToRemove) properties.remove(property);
    // Catch the case where someone passed a kwarg that is not recognized.
    for (String bogus : Sets.difference(properties.keySet(), allowedKeywords))
      throw new InvalidRequestException(
          bogus + " is not a valid keyword argument for CREATE COLUMNFAMILY");
    for (String obsolete : Sets.intersection(properties.keySet(), obsoleteKeywords))
      logger.warn("Ignoring obsolete property {}", obsolete);

    // Validate min/max compaction thresholds
    Integer minCompaction = getPropertyInt(KW_MINCOMPACTIONTHRESHOLD, null);
    Integer maxCompaction = getPropertyInt(KW_MAXCOMPACTIONTHRESHOLD, null);

    if ((minCompaction != null) && (maxCompaction != null)) // Both min and max are set
    {
      if ((minCompaction > maxCompaction) && (maxCompaction != 0))
        throw new InvalidRequestException(
            String.format(
                "%s cannot be larger than %s",
                KW_MINCOMPACTIONTHRESHOLD, KW_MAXCOMPACTIONTHRESHOLD));
    } else if (minCompaction != null) // Only the min threshold is set
    {
      if (minCompaction > CFMetaData.DEFAULT_MAX_COMPACTION_THRESHOLD)
        throw new InvalidRequestException(
            String.format(
                "%s cannot be larger than %s, (default %s)",
                KW_MINCOMPACTIONTHRESHOLD,
                KW_MAXCOMPACTIONTHRESHOLD,
                CFMetaData.DEFAULT_MAX_COMPACTION_THRESHOLD));
    } else if (maxCompaction != null) // Only the max threshold is set
    {
      if ((maxCompaction < CFMetaData.DEFAULT_MIN_COMPACTION_THRESHOLD) && (maxCompaction != 0))
        throw new InvalidRequestException(
            String.format(
                "%s cannot be smaller than %s, (default %s)",
                KW_MAXCOMPACTIONTHRESHOLD,
                KW_MINCOMPACTIONTHRESHOLD,
                CFMetaData.DEFAULT_MIN_COMPACTION_THRESHOLD));
    }

    CFMetaData.validateCompactionOptions(compactionStrategyClass, compactionStrategyOptions);
  }
Beispiel #24
0
 public static ByteBuffer buildName(CFMetaData meta, ByteBuffer... args) {
   ColumnNameBuilder builder = meta.getCfDef().getColumnNameBuilder();
   for (ByteBuffer arg : args) builder.add(arg);
   return builder.build();
 }
Beispiel #25
0
 private static AbstractType[] getKeyTypes(CFMetaData cfm) {
   AbstractType[] types = new AbstractType[cfm.getCfDef().keys.size()];
   int i = 0;
   for (CFDefinition.Name name : cfm.getCfDef().keys.values()) types[i++] = name.type;
   return types;
 }
Beispiel #26
0
 public TokenFct(CFMetaData cfm) {
   super("token", partitioner.getTokenValidator(), getKeyTypes(cfm));
   this.cfDef = cfm.getCfDef();
 }
  public CFDefinition(CFMetaData cfm) {
    this.cfm = cfm;

    if (cfm.getKeyValidator() instanceof CompositeType) {
      this.hasCompositeKey = true;
      CompositeType keyComposite = (CompositeType) cfm.getKeyValidator();
      assert keyComposite.types.size() > 1;
      for (int i = 0; i < keyComposite.types.size(); i++) {
        ColumnIdentifier id = getKeyId(cfm, i);
        this.keys.put(
            id,
            new Name(
                cfm.ksName, cfm.cfName, id, Name.Kind.KEY_ALIAS, i, keyComposite.types.get(i)));
      }
    } else {
      this.hasCompositeKey = false;
      ColumnIdentifier id = getKeyId(cfm, 0);
      this.keys.put(
          id, new Name(cfm.ksName, cfm.cfName, id, Name.Kind.KEY_ALIAS, 0, cfm.getKeyValidator()));
    }

    if (cfm.comparator instanceof CompositeType) {
      this.isComposite = true;
      CompositeType composite = (CompositeType) cfm.comparator;
      /*
       * We are a "sparse" composite, i.e. a non-compact one, if either:
       *   - the last type of the composite is a ColumnToCollectionType
       *   - or we have one less alias than of composite types and the last type is UTF8Type.
       *
       * Note that this is not perfect: if someone upgrading from thrift "renames" all but
       * the last column alias, the cf will be considered "sparse" and he will be stuck with
       * that even though that might not be what he wants. But the simple workaround is
       * for that user to rename all the aliases at the same time in the first place.
       */
      int last = composite.types.size() - 1;
      AbstractType<?> lastType = composite.types.get(last);
      if (lastType instanceof ColumnToCollectionType
          || (cfm.getColumnAliases().size() == last && lastType instanceof UTF8Type)) {
        // "sparse" composite
        this.isCompact = false;
        this.value = null;
        assert cfm.getValueAlias() == null;
        // check for collection type
        if (lastType instanceof ColumnToCollectionType) {
          --last;
          this.hasCollections = true;
        } else {
          this.hasCollections = false;
        }

        for (int i = 0; i < last; i++) {
          ColumnIdentifier id = getColumnId(cfm, i);
          this.columns.put(
              id,
              new Name(
                  cfm.ksName, cfm.cfName, id, Name.Kind.COLUMN_ALIAS, i, composite.types.get(i)));
        }

        for (Map.Entry<ByteBuffer, ColumnDefinition> def : cfm.getColumn_metadata().entrySet()) {
          ColumnIdentifier id =
              new ColumnIdentifier(def.getKey(), cfm.getColumnDefinitionComparator(def.getValue()));
          this.metadata.put(
              id,
              new Name(
                  cfm.ksName,
                  cfm.cfName,
                  id,
                  Name.Kind.COLUMN_METADATA,
                  def.getValue().getValidator()));
        }
      } else {
        // "dense" composite
        this.isCompact = true;
        this.hasCollections = false;
        for (int i = 0; i < composite.types.size(); i++) {
          ColumnIdentifier id = getColumnId(cfm, i);
          this.columns.put(
              id,
              new Name(
                  cfm.ksName, cfm.cfName, id, Name.Kind.COLUMN_ALIAS, i, composite.types.get(i)));
        }
        this.value = createValue(cfm);
      }
    } else {
      this.isComposite = false;
      this.hasCollections = false;
      if (!cfm.getColumnAliases().isEmpty() || cfm.getColumn_metadata().isEmpty()) {
        // dynamic CF
        this.isCompact = true;
        ColumnIdentifier id = getColumnId(cfm, 0);
        Name name = new Name(cfm.ksName, cfm.cfName, id, Name.Kind.COLUMN_ALIAS, 0, cfm.comparator);
        this.columns.put(id, name);
        this.value = createValue(cfm);
      } else {
        // static CF
        this.isCompact = false;
        this.value = null;
        assert cfm.getValueAlias() == null;
        assert cfm.getColumnAliases() == null || cfm.getColumnAliases().isEmpty();
        for (Map.Entry<ByteBuffer, ColumnDefinition> def : cfm.getColumn_metadata().entrySet()) {
          ColumnIdentifier id =
              new ColumnIdentifier(def.getKey(), cfm.getColumnDefinitionComparator(def.getValue()));
          this.metadata.put(
              id,
              new Name(
                  cfm.ksName,
                  cfm.cfName,
                  id,
                  Name.Kind.COLUMN_METADATA,
                  def.getValue().getValidator()));
        }
      }
    }
    assert value == null || metadata.isEmpty();
  }
 /** Returns true if the slice includes static columns, false otherwise. */
 private boolean sliceIncludesStatics(ColumnSlice slice, CFMetaData cfm) {
   return cfm.hasStaticColumns()
       && slice.includes(
           reversed ? cfm.comparator.reverseComparator() : cfm.comparator,
           cfm.comparator.staticPrefix().end());
 }
  /**
   * Given arguments specifying an SSTable, and optionally an output file, export the contents of
   * the SSTable to JSON.
   *
   * @param args command lines arguments
   * @throws ConfigurationException on configuration failure (wrong params given)
   */
  public static void main(String[] args) throws ConfigurationException {
    CommandLineParser parser = new PosixParser();
    try {
      cmd = parser.parse(options, args);
    } catch (ParseException e1) {
      System.err.println(e1.getMessage());
      printUsage();
      System.exit(1);
    }

    if (cmd.getArgs().length != 1) {
      System.err.println("You must supply exactly one sstable");
      printUsage();
      System.exit(1);
    }

    String[] keys = cmd.getOptionValues(KEY_OPTION);
    HashSet<String> excludes =
        new HashSet<>(
            Arrays.asList(
                cmd.getOptionValues(EXCLUDE_KEY_OPTION) == null
                    ? new String[0]
                    : cmd.getOptionValues(EXCLUDE_KEY_OPTION)));
    String ssTableFileName = new File(cmd.getArgs()[0]).getAbsolutePath();

    if (Descriptor.isLegacyFile(new File(ssTableFileName))) {
      System.err.println("Unsupported legacy sstable");
      System.exit(1);
    }
    if (!new File(ssTableFileName).exists()) {
      System.err.println("Cannot find file " + ssTableFileName);
      System.exit(1);
    }
    Descriptor desc = Descriptor.fromFilename(ssTableFileName);
    try {
      CFMetaData metadata = metadataFromSSTable(desc);
      if (cmd.hasOption(ENUMERATE_KEYS_OPTION)) {
        JsonTransformer.keysToJson(
            null,
            iterToStream(new KeyIterator(desc, metadata)),
            cmd.hasOption(RAW_TIMESTAMPS),
            metadata,
            System.out);
      } else {
        SSTableReader sstable = SSTableReader.openNoValidation(desc, metadata);
        IPartitioner partitioner = sstable.getPartitioner();
        final ISSTableScanner currentScanner;
        if ((keys != null) && (keys.length > 0)) {
          List<AbstractBounds<PartitionPosition>> bounds =
              Arrays.stream(keys)
                  .filter(key -> !excludes.contains(key))
                  .map(metadata.getKeyValidator()::fromString)
                  .map(partitioner::decorateKey)
                  .sorted()
                  .map(DecoratedKey::getToken)
                  .map(token -> new Bounds<>(token.minKeyBound(), token.maxKeyBound()))
                  .collect(Collectors.toList());
          currentScanner = sstable.getScanner(bounds.iterator());
        } else {
          currentScanner = sstable.getScanner();
        }
        Stream<UnfilteredRowIterator> partitions =
            iterToStream(currentScanner)
                .filter(
                    i ->
                        excludes.isEmpty()
                            || !excludes.contains(
                                metadata.getKeyValidator().getString(i.partitionKey().getKey())));
        if (cmd.hasOption(DEBUG_OUTPUT_OPTION)) {
          AtomicLong position = new AtomicLong();
          partitions.forEach(
              partition -> {
                position.set(currentScanner.getCurrentPosition());

                if (!partition.partitionLevelDeletion().isLive()) {
                  System.out.println(
                      "["
                          + metadata.getKeyValidator().getString(partition.partitionKey().getKey())
                          + "]@"
                          + position.get()
                          + " "
                          + partition.partitionLevelDeletion());
                }
                if (!partition.staticRow().isEmpty()) {
                  System.out.println(
                      "["
                          + metadata.getKeyValidator().getString(partition.partitionKey().getKey())
                          + "]@"
                          + position.get()
                          + " "
                          + partition.staticRow().toString(metadata, true));
                }
                partition.forEachRemaining(
                    row -> {
                      System.out.println(
                          "["
                              + metadata
                                  .getKeyValidator()
                                  .getString(partition.partitionKey().getKey())
                              + "]@"
                              + position.get()
                              + " "
                              + row.toString(metadata, false, true));
                      position.set(currentScanner.getCurrentPosition());
                    });
              });
        } else {
          JsonTransformer.toJson(
              currentScanner, partitions, cmd.hasOption(RAW_TIMESTAMPS), metadata, System.out);
        }
      }
    } catch (IOException e) {
      // throwing exception outside main with broken pipe causes windows cmd to hang
      e.printStackTrace(System.err);
    }

    System.exit(0);
  }
  public void validate(ClientState state) throws RequestValidationException {
    CFMetaData cfm = ThriftValidation.validateColumnFamily(keyspace(), columnFamily());
    if (cfm.isCounter())
      throw new InvalidRequestException("Secondary indexes are not supported on counter tables");

    IndexTarget target = rawTarget.prepare(cfm);
    ColumnDefinition cd = cfm.getColumnDefinition(target.column);

    if (cd == null)
      throw new InvalidRequestException("No column definition found for column " + target.column);

    boolean isMap = cd.type instanceof MapType;
    boolean isFrozenCollection = cd.type.isCollection() && !cd.type.isMultiCell();
    if (target.isCollectionKeys) {
      if (!isMap)
        throw new InvalidRequestException(
            "Cannot create index on keys of column " + target + " with non-map type");
      if (!cd.type.isMultiCell())
        throw new InvalidRequestException(
            "Cannot create index on keys of frozen<map> column " + target);
    } else if (target.isFullCollection) {
      if (!isFrozenCollection)
        throw new InvalidRequestException(
            "full() indexes can only be created on frozen collections");
    } else if (isFrozenCollection) {
      throw new InvalidRequestException(
          "Frozen collections currently only support full-collection indexes. "
              + "For example, 'CREATE INDEX ON <table>(full(<columnName>))'.");
    }

    if (cd.getIndexType() != null) {
      boolean previousIsKeys = cd.hasIndexOption(SecondaryIndex.INDEX_KEYS_OPTION_NAME);
      if (isMap && target.isCollectionKeys != previousIsKeys) {
        String msg =
            "Cannot create index on %s %s, an index on %s %s already exists and indexing "
                + "a map on both keys and values at the same time is not currently supported";
        throw new InvalidRequestException(
            String.format(
                msg,
                target.column,
                target.isCollectionKeys ? "keys" : "values",
                target.column,
                previousIsKeys ? "keys" : "values"));
      }

      if (ifNotExists) return;
      else throw new InvalidRequestException("Index already exists");
    }

    properties.validate();

    // TODO: we could lift that limitation
    if ((cfm.comparator.isDense() || !cfm.comparator.isCompound())
        && cd.kind != ColumnDefinition.Kind.REGULAR)
      throw new InvalidRequestException(
          "Secondary indexes are not supported on PRIMARY KEY columns in COMPACT STORAGE tables");

    // It would be possible to support 2ndary index on static columns (but not without modifications
    // of at least ExtendedFilter and
    // CompositesIndex) and maybe we should, but that means a query like:
    //     SELECT * FROM foo WHERE static_column = 'bar'
    // would pull the full partition every time the static column of partition is 'bar', which
    // sounds like offering a
    // fair potential for foot-shooting, so I prefer leaving that to a follow up ticket once we have
    // identified cases where
    // such indexing is actually useful.
    if (cd.isStatic())
      throw new InvalidRequestException("Secondary indexes are not allowed on static columns");

    if (cd.kind == ColumnDefinition.Kind.PARTITION_KEY && cd.isOnAllComponents())
      throw new InvalidRequestException(
          String.format("Cannot create secondary index on partition key column %s", target.column));
  }