maedhroz commented on code in PR #4175: URL: https://github.com/apache/cassandra/pull/4175#discussion_r2164791690
########## src/java/org/apache/cassandra/service/accord/txn/TxnReference.java: ########## @@ -163,192 +140,485 @@ public Row getRow(TxnData data) public Row getRow(FilteredPartition partition) { - if (column != null && column.isStatic()) + if (kind == Kind.COLUMN && asColumn().column.isStatic()) return partition.staticRow(); assert partition.rowCount() <= 1 : "Multi-row references are not allowed"; if (partition.rowCount() == 0) return null; return partition.getAtIdx(0); } - public ColumnData getColumnData(Row row) + public static final UnversionedSerializer<RowReference> rowSerializer = new UnversionedSerializer<>() { - if (column.isComplex() && path == null) - return row.getComplexColumnData(column); + @Override + public void serialize(RowReference reference, DataOutputPlus out) throws IOException + { + out.writeUnsignedVInt32(reference.tuple); + } - if (path != null && column.type.isMultiCell()) + @Override + public RowReference deserialize(DataInputPlus in) throws IOException { - if (column.type.isCollection()) - { - CollectionType<?> collectionType = (CollectionType<?>) column.type; + int tuple = in.readUnsignedVInt32(); + return row(tuple); + } - if (collectionType.kind == CollectionType.Kind.LIST) - return row.getComplexColumnData(column).getCellByIndex(ByteBufferUtil.toInt(path.get(0))); - } + @Override + public long serializedSize(RowReference reference) + { + return VIntCoding.sizeOfUnsignedVInt(reference.tuple); + } + }; - return row.getCell(column, path); + public static final ParameterisedUnversionedSerializer<ColumnReference, TableMetadatas> columnSerializer = new ParameterisedUnversionedSerializer<ColumnReference, TableMetadatas>() + { + @Override + public void serialize(ColumnReference reference, TableMetadatas tables, DataOutputPlus out) throws IOException + { + out.writeUnsignedVInt32(reference.tuple); + tables.serialize(reference.table, out); + columnMetadataSerializer.serialize(reference.column, reference.table, out); + out.writeBoolean(reference.path != null); + if (reference.path != null) + CollectionType.cellPathSerializer.serialize(reference.path, out); } - return row.getCell(column); - } + @Override + public ColumnReference deserialize(TableMetadatas tables, DataInputPlus in) throws IOException + { + int tuple = in.readUnsignedVInt32(); + TableMetadata table = tables.deserialize(in); + ColumnMetadata column = columnMetadataSerializer.deserialize(table, in); + CellPath path = in.readBoolean() ? CollectionType.cellPathSerializer.deserialize(in) : null; + return TxnReference.column(tuple, table, column, path); + } - public ColumnData getColumnData(TxnData data) - { - Row row = getRow(data); - return row != null ? getColumnData(row) : null; - } + @Override + public long serializedSize(ColumnReference reference, TableMetadatas tables) + { + long size = 0; + size += VIntCoding.sizeOfUnsignedVInt(reference.tuple); + size += tables.serializedSize(reference.table); + size += columnMetadataSerializer.serializedSize(reference.column, reference.table); + size += TypeSizes.BOOL_SIZE; + if (reference.path != null) + size += CollectionType.cellPathSerializer.serializedSize(reference.path); + return size; + } + }; - public ByteBuffer getFrozenCollectionElement(Cell<?> collection) - { - CollectionType<?> collectionType = (CollectionType<?>) column.type; - return collectionType.getSerializer().getSerializedValue(collection.buffer(), path.get(0), collectionType.nameComparator()); - } - public ByteBuffer getFrozenFieldValue(Cell<?> udt) + static final ParameterisedUnversionedSerializer<TxnReference, TableMetadatas> serializer = new ParameterisedUnversionedSerializer<>() { - UserType userType = (UserType) column.type; - int field = ByteBufferUtil.getUnsignedShort(path.get(0), 0); - return userType.unpack(udt.buffer()).get(field); - } + @Override + public void serialize(TxnReference reference, TableMetadatas tables, DataOutputPlus out) throws IOException + { + out.writeUnsignedVInt32(TinyEnumSet.encode(reference.kind)); + switch (reference.kind) + { + case ROW: + rowSerializer.serialize(reference.asRow(), out); + break; + case COLUMN: + columnSerializer.serialize(reference.asColumn(), tables, out); + break; + default: + throw new UnhandledEnum(reference.kind); + } + } + + @Override + public TxnReference deserialize(TableMetadatas tables, DataInputPlus in) throws IOException + { + TinyEnumSet<TxnReference.Kind> kind = new TinyEnumSet<>(in.readUnsignedVInt32()); + if (kind.contains(Kind.ROW)) return rowSerializer.deserialize(in); + if (kind.contains(Kind.COLUMN)) return columnSerializer.deserialize(tables, in); + throw Invariants.illegalArgument("Unexpected kind: " + kind); + } + + @Override + public long serializedSize(TxnReference reference, TableMetadatas tables) + { + long size = VIntCoding.sizeOfUnsignedVInt(TinyEnumSet.encode(reference.kind)); + switch (reference.kind) + { + case ROW: + size += rowSerializer.serializedSize(reference.asRow()); + break; + case COLUMN: + size += columnSerializer.serializedSize(reference.asColumn(), tables); + break; + default: + throw new UnhandledEnum(reference.kind); + } + return size; + } + }; - public AbstractType<?> getFieldSelectionType() + public enum Kind { ROW, COLUMN } + + public static class RowReference extends TxnReference { - assert isFieldSelection() : "No field selection type exists"; - UserType userType = (UserType) column.type; - int field = ByteBufferUtil.getUnsignedShort(path.get(0), 0); - return userType.fieldType(field); + public RowReference(int tuple) + { + super(Kind.ROW, tuple); + } + + @Override + public void collect(TableMetadatas.Collector collector) + { + // no-op + } + + @Override + public boolean equals(Object o) + { + if (o == null || getClass() != o.getClass()) return false; + RowReference that = (RowReference) o; + return tuple == that.tuple; + } + + @Override + public int hashCode() + { + return Objects.hash(tuple); + } + + @Override + public String toString() + { + return Integer.toString(tuple); + } } - public ByteBuffer toByteBuffer(TxnData data, AbstractType<?> receiver) + public static class ColumnReference extends TxnReference { - // TODO: confirm all references can be satisfied as part of the txn condition - AbstractType<?> type = column().type; + private final TableMetadata table; + private final ColumnMetadata column; + @Nullable + private final CellPath path; + + public ColumnReference(int tuple, TableMetadata table, ColumnMetadata column, @Nullable CellPath path) + { + super(Kind.COLUMN, tuple); + this.table = table; + this.column = column; + this.path = path; + } + + public ColumnMetadata column() + { + return column; + } + + public TableMetadata table() + { + return table; + } + + @Nullable + public CellPath path() + { + return path; + } + + public boolean selectsPath() + { + return path != null; + } + + public boolean isElementSelection() + { + return selectsPath() && column.type.isCollection(); + } + + public boolean isFieldSelection() + { + return selectsPath() && column.type.isUDT(); + } + + public ByteBuffer getPartitionKey(TxnData data) + { + FilteredPartition partition = getPartition(data); + if (partition == null) return null; + return partition.metadata().partitionKeyColumns().size() == 1 + ? partition.partitionKey().getKey() + : ((CompositeType) partition.metadata().partitionKeyType).split(partition.partitionKey().getKey())[column.position()]; + } + + @Override + public void collect(TableMetadatas.Collector collector) + { + collector.add(table); + } + + public ByteBuffer getClusteringKey(TxnData data) + { + Row row = getRow(data); + if (row == null) + return null; + return row.clustering().bufferAt(column.position()); + } - // Modify the type we'll check if the reference is to a collection element. - if (selectsPath()) + public ColumnData getColumnData(Row row) { - if (type.isCollection()) + if (column.isClusteringColumn()) + return new ClusteringColumnData(column, row.clustering().bufferAt(column.position())); + if (column.isComplex() && path == null) + return row.getComplexColumnData(column); + + if (path != null && column.type.isMultiCell()) { - CollectionType<?> collectionType = (CollectionType<?>) type; - type = collectionType.kind == SET ? collectionType.nameComparator() : collectionType.valueComparator(); + if (column.type.isCollection()) + { + CollectionType<?> collectionType = (CollectionType<?>) column.type; + + if (collectionType.kind == CollectionType.Kind.LIST) + return row.getComplexColumnData(column).getCellByIndex(ByteBufferUtil.toInt(path.get(0))); + } + + return row.getCell(column, path); } - else if (type.isUDT()) - type = getFieldSelectionType(); + + return row.getCell(column); + } + + public ColumnData getColumnData(TxnData data) + { + Row row = getRow(data); + return row != null ? getColumnData(row) : null; } - // Account for frozen collection and reversed clustering key references: - AbstractType<?> receiveType = type.isFrozenCollection() ? receiver.freeze().unwrap() : receiver.unwrap(); - if (!(receiveType == type.unwrap())) - throw new IllegalArgumentException("Receiving type " + receiveType + " does not match " + type.unwrap()); + public ByteBuffer getFrozenCollectionElement(Cell<?> collection) + { + CollectionType<?> collectionType = (CollectionType<?>) column.type.unwrap(); + return collectionType.getSerializer().getSerializedValue(collection.buffer(), path.get(0), collectionType.nameComparator()); + } - if (column().isPartitionKey()) - return getPartitionKey(data); - else if (column().isClusteringColumn()) - return getClusteringKey(data); + public AbstractType<?> getFrozenCollectionElementType() + { + CollectionType<?> type = (CollectionType<?>) column.type.unwrap(); + if (type instanceof ListType) return Int32Type.instance; // by index is the only thing supported right now; see getFrozenCollectionElement + return type.nameComparator(); + } - ColumnData columnData = getColumnData(data); + public ByteBuffer getFrozenFieldValue(Cell<?> udt) + { + UserType userType = (UserType) column.type.unwrap(); + int field = ByteBufferUtil.getUnsignedShort(path.get(0), 0); + List<ByteBuffer> tuple = userType.unpack(udt.buffer()); + return tuple.size() > field ? tuple.get(field) : null; + } - if (columnData == null) - return null; + public AbstractType<?> getFieldSelectionType() + { + assert isFieldSelection() : "No field selection type exists"; + UserType userType = (UserType) column.type; + int field = ByteBufferUtil.getUnsignedShort(path.get(0), 0); Review Comment: Even though `path` is `@Nullable`, I think here and in a couple places directly above, all callers are still in situations where `path` should be non-null. Not sure if we want to make some assertions here, but things would blow up when misused either way. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: pr-unsubscr...@cassandra.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: pr-unsubscr...@cassandra.apache.org For additional commands, e-mail: pr-h...@cassandra.apache.org