private Mutation makeMutation()

in cassandra-four-zero/src/main/java/org/apache/cassandra/bridge/CassandraBridgeImplementation.java [694:831]


    private Mutation makeMutation(CqlTable cqlTable, IRow row, long timestamp)
    {
        TableMetadata table = Schema.instance.getTableMetadata(cqlTable.keyspace(), cqlTable.table());
        assert table != null;

        Row.Builder rowBuilder = BTreeRow.sortedBuilder();
        if (row.isInsert())
        {
            rowBuilder.addPrimaryKeyLivenessInfo(LivenessInfo.create(timestamp, timeProvider().nowInTruncatedSeconds()));
        }
        Row staticRow = Rows.EMPTY_STATIC_ROW;

        // Build partition key
        List<CqlField> partitionKeys = cqlTable.partitionKeys();
        ByteBuffer partitionKey = ColumnTypes.buildPartitionKey(partitionKeys,
                                                                partitionKeys.stream()
                                                                             .map(field -> row.get(field.position()))
                                                                             .toArray());

        DecoratedKey decoratedPartitionKey = table.partitioner.decorateKey(partitionKey);

        // Create a mutation and return early
        if (isPartitionDeletion(cqlTable, row))
        {
            PartitionUpdate delete = PartitionUpdate.fullPartitionDelete(table, partitionKey, timestamp, timeProvider().nowInTruncatedSeconds());
            return new Mutation(delete);
        }

        List<CqlField> clusteringKeys = cqlTable.clusteringKeys();

        // Create a mutation with range tombstones
        if (row.rangeTombstones() != null && !row.rangeTombstones().isEmpty())
        {
            PartitionUpdate.SimpleBuilder updateBuilder = PartitionUpdate.simpleBuilder(table, decoratedPartitionKey)
                                                                         .timestamp(timestamp)
                                                                         .nowInSec(timeProvider().nowInTruncatedSeconds());
            for (RangeTombstone rangeTombstone : row.rangeTombstones())
            {
                // Range tombstone builder is built when partition update builder builds
                PartitionUpdate.SimpleBuilder.RangeTombstoneBuilder tombstoneBuilder = updateBuilder.addRangeTombstone();
                // Returns the same ref. just to make compiler happy
                tombstoneBuilder = rangeTombstone.open.inclusive ? tombstoneBuilder.inclStart() : tombstoneBuilder.exclStart();
                Object[] startValues = clusteringKeys.stream()
                                                     .map(field -> {
                                                         Object value = rangeTombstone.open.values[field.position() - cqlTable.numPartitionKeys()];
                                                         return value != null ? field.serialize(value) : null;
                                                     })
                                                     .filter(Objects::nonNull)
                                                     .toArray(ByteBuffer[]::new);
                tombstoneBuilder.start(startValues);
                tombstoneBuilder = rangeTombstone.close.inclusive ? tombstoneBuilder.inclEnd() : tombstoneBuilder.exclEnd();
                Object[] endValues = clusteringKeys.stream()
                                                   .map(field -> {
                                                       Object value = rangeTombstone.close.values[field.position() - cqlTable.numPartitionKeys()];
                                                       return value != null ? field.serialize(value) : null;
                                                   })
                                                   .filter(Objects::nonNull)
                                                   .toArray(ByteBuffer[]::new);
                tombstoneBuilder.end(endValues);
            }
            return new Mutation(updateBuilder.build());
        }

        // Build clustering key
        if (!clusteringKeys.isEmpty())
        {
            rowBuilder.newRow(Clustering.make(clusteringKeys.stream()
                                                            .map(field -> field.serialize(row.get(field.position())))
                                                            .toArray(ByteBuffer[]::new)));
        }
        else
        {
            rowBuilder.newRow(Clustering.EMPTY);
        }

        if (!row.isDeleted())
        {
            BiConsumer<Row.Builder, CqlField> rowBuildFunc = (builder, field) -> {
                CqlType type = (CqlType) field.type();
                ColumnMetadata column = table.getColumn(new ColumnIdentifier(field.name(), false));
                Object value = row.get(field.position());
                if (value == CassandraBridge.UNSET_MARKER)
                {
                    // CHECKSTYLE IGNORE: Do not add the cell, a.k.a. unset
                }
                else if (value == null)
                {
                    if (column.isComplex())
                    {
                        type.addComplexTombstone(builder, column, timestamp);
                    }
                    else
                    {
                        type.addTombstone(builder, column, timestamp);
                    }
                }
                else if (value instanceof CollectionElement)
                {
                    CollectionElement element = (CollectionElement) value;
                    if (element.value == null)
                    {
                        type.addTombstone(builder, column, timestamp, element.cellPath);
                    }
                    else
                    {
                        type.addCell(builder, column, timestamp, element.value, element.cellPath);
                    }
                }
                else
                {
                    type.addCell(builder, column, timestamp, value);
                }
            };

            if (!cqlTable.staticColumns().isEmpty())
            {
                Row.Builder staticRowBuilder = BTreeRow.sortedBuilder();
                staticRowBuilder.newRow(Clustering.STATIC_CLUSTERING);
                for (CqlField field : cqlTable.staticColumns())
                {
                    rowBuildFunc.accept(staticRowBuilder, field);
                }
                staticRow = staticRowBuilder.build();  // Replace the empty row with the new static row built
            }

            // Build value cells
            for (CqlField field : cqlTable.valueColumns())
            {
                rowBuildFunc.accept(rowBuilder, field);
            }
        }
        else
        {
            rowBuilder.addRowDeletion(Row.Deletion.regular(new DeletionTime(timestamp, timeProvider().nowInTruncatedSeconds())));
        }

        return new Mutation(PartitionUpdate.singleRowUpdate(table, decoratedPartitionKey, rowBuilder.build(), staticRow));
    }