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));
}