
com.datastax.oss.protocol.internal.response.result.RowsMetadata Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of native-protocol Show documentation
Show all versions of native-protocol Show documentation
A set of Java types representing the frames and messages of the Apache Cassandra® native
protocol, with the associated serialization and deserialization logic (this is a third-party
implementation, not related to the Apache Cassandra project)
The newest version!
/*
* Copyright DataStax, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.datastax.oss.protocol.internal.response.result;
import com.datastax.oss.protocol.internal.PrimitiveCodec;
import com.datastax.oss.protocol.internal.PrimitiveSizes;
import com.datastax.oss.protocol.internal.ProtocolConstants;
import com.datastax.oss.protocol.internal.util.Flags;
import com.datastax.oss.protocol.internal.util.collection.NullAllowingImmutableList;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class RowsMetadata {
/**
* empty if and only if the SKIP_METADATA flag is present (there is no difference between skipping
* the column specs, and having the specs but no columns in them)
*/
public final List columnSpecs;
public final int columnCount;
public final ByteBuffer pagingState;
public final int[] pkIndices;
public final byte[] newResultMetadataId;
public final int flags;
/**
* Builds a new instance with {@code NO_METADATA == false}; the column count is set to the number
* of column specifications in the provided list.
*/
public RowsMetadata(
List columnSpecs,
ByteBuffer pagingState,
int[] pkIndices,
byte[] newResultMetadataId) {
this(
computeFlags(false, columnSpecs, pagingState, newResultMetadataId),
columnSpecs,
columnSpecs.size(),
pagingState,
pkIndices,
newResultMetadataId);
}
/** Builds a new instance with {@code NO_METADATA == true}. */
public RowsMetadata(
int columnCount, ByteBuffer pagingState, int[] pkIndices, byte[] newResultMetadataId) {
this(
computeFlags(true, Collections.emptyList(), pagingState, newResultMetadataId),
Collections.emptyList(),
columnCount,
pagingState,
pkIndices,
newResultMetadataId);
}
/**
* This constructor should only be used in message codecs. To build an outgoing message from
* client code, use {@link #RowsMetadata(int, ByteBuffer, int[], byte[])} or {@link
* #RowsMetadata(List, ByteBuffer, int[], byte[])} so that the flags are computed automatically.
*/
public RowsMetadata(
int flags,
List columnSpecs,
int columnCount,
ByteBuffer pagingState,
int[] pkIndices,
byte[] newResultMetadataId) {
this.columnSpecs = columnSpecs;
this.columnCount = columnCount;
this.pagingState = pagingState;
this.pkIndices = pkIndices;
this.newResultMetadataId = newResultMetadataId;
this.flags = flags;
}
protected static int computeFlags(
boolean noMetadata,
List columnSpecs,
ByteBuffer pagingState,
byte[] newResultMetadataId) {
int flags = 0;
if (noMetadata) {
flags = Flags.add(flags, ProtocolConstants.RowsFlag.NO_METADATA);
} else if (haveSameTable(columnSpecs)) {
flags = Flags.add(flags, ProtocolConstants.RowsFlag.GLOBAL_TABLES_SPEC);
}
if (pagingState != null) {
flags = Flags.add(flags, ProtocolConstants.RowsFlag.HAS_MORE_PAGES);
}
if (newResultMetadataId != null) {
flags = Flags.add(flags, ProtocolConstants.RowsFlag.METADATA_CHANGED);
}
return flags;
}
public void encode(
B dest, PrimitiveCodec encoder, boolean withPkIndices, int protocolVersion) {
encoder.writeInt(flags, dest);
encoder.writeInt(columnCount, dest);
if (withPkIndices) {
if (pkIndices == null) {
encoder.writeInt(0, dest);
} else {
encoder.writeInt(pkIndices.length, dest);
for (int pkIndex : pkIndices) {
encoder.writeUnsignedShort(pkIndex, dest);
}
}
}
if (Flags.contains(flags, ProtocolConstants.RowsFlag.HAS_MORE_PAGES)) {
encoder.writeBytes(pagingState, dest);
}
if (Flags.contains(flags, ProtocolConstants.RowsFlag.METADATA_CHANGED)) {
encoder.writeShortBytes(newResultMetadataId, dest);
}
if (!Flags.contains(flags, ProtocolConstants.RowsFlag.NO_METADATA) && !columnSpecs.isEmpty()) {
boolean globalTable = Flags.contains(flags, ProtocolConstants.RowsFlag.GLOBAL_TABLES_SPEC);
if (globalTable) {
ColumnSpec firstSpec = columnSpecs.get(0);
encoder.writeString(firstSpec.ksName, dest);
encoder.writeString(firstSpec.tableName, dest);
}
for (ColumnSpec spec : columnSpecs) {
if (!globalTable) {
encoder.writeString(spec.ksName, dest);
encoder.writeString(spec.tableName, dest);
}
encoder.writeString(spec.name, dest);
spec.type.encode(dest, encoder, protocolVersion);
}
}
}
public int encodedSize(boolean withPkIndices, int protocolVersion) {
int size = PrimitiveSizes.INT; // flags
size += PrimitiveSizes.INT; // column count
if (Flags.contains(flags, ProtocolConstants.RowsFlag.METADATA_CHANGED)) {
size += PrimitiveSizes.sizeOfShortBytes(newResultMetadataId);
}
if (withPkIndices) {
size += PrimitiveSizes.INT;
if (pkIndices != null) {
size += pkIndices.length * PrimitiveSizes.SHORT;
}
}
if (Flags.contains(flags, ProtocolConstants.RowsFlag.HAS_MORE_PAGES)) {
size += PrimitiveSizes.sizeOfBytes(pagingState);
}
if (!Flags.contains(flags, ProtocolConstants.RowsFlag.NO_METADATA) && !columnSpecs.isEmpty()) {
boolean globalTable = Flags.contains(flags, ProtocolConstants.RowsFlag.GLOBAL_TABLES_SPEC);
if (globalTable) {
ColumnSpec firstSpec = columnSpecs.get(0);
size += PrimitiveSizes.sizeOfString(firstSpec.ksName);
size += PrimitiveSizes.sizeOfString(firstSpec.tableName);
}
for (ColumnSpec spec : columnSpecs) {
if (!globalTable) {
size += PrimitiveSizes.sizeOfString(spec.ksName);
size += PrimitiveSizes.sizeOfString(spec.tableName);
}
size += PrimitiveSizes.sizeOfString(spec.name);
size += spec.type.encodedSize(protocolVersion);
}
}
return size;
}
public static RowsMetadata decode(
B source, PrimitiveCodec decoder, boolean withPkIndices, int protocolVersion) {
int flags = decoder.readInt(source);
int columnCount = decoder.readInt(source);
int[] pkIndices = null;
int pkCount;
if (withPkIndices && (pkCount = decoder.readInt(source)) > 0) {
pkIndices = new int[pkCount];
for (int i = 0; i < pkCount; i++) {
pkIndices[i] = decoder.readUnsignedShort(source);
}
}
ByteBuffer state =
(Flags.contains(flags, ProtocolConstants.RowsFlag.HAS_MORE_PAGES))
? decoder.readBytes(source)
: null;
byte[] newResultMetadataId =
(Flags.contains(flags, ProtocolConstants.RowsFlag.METADATA_CHANGED))
? decoder.readShortBytes(source)
: null;
List columnSpecs;
if (Flags.contains(flags, ProtocolConstants.RowsFlag.NO_METADATA)) {
columnSpecs = Collections.emptyList();
} else {
boolean globalTablesSpec =
Flags.contains(flags, ProtocolConstants.RowsFlag.GLOBAL_TABLES_SPEC);
String globalKsName = null;
String globalCfName = null;
if (globalTablesSpec) {
globalKsName = decoder.readString(source);
globalCfName = decoder.readString(source);
}
NullAllowingImmutableList.Builder builder =
NullAllowingImmutableList.builder(columnCount);
for (int i = 0; i < columnCount; i++) {
String ksName = globalTablesSpec ? globalKsName : decoder.readString(source);
String cfName = globalTablesSpec ? globalCfName : decoder.readString(source);
String name = decoder.readString(source);
RawType type = RawType.decode(source, decoder, protocolVersion);
builder.add(new ColumnSpec(ksName, cfName, name, i, type));
}
columnSpecs = builder.build();
}
return new RowsMetadata(flags, columnSpecs, columnCount, state, pkIndices, newResultMetadataId);
}
private static boolean haveSameTable(List specs) {
if (specs.isEmpty()) {
return false;
}
boolean first = true;
String ksName = null;
String tableName = null;
for (ColumnSpec spec : specs) {
if (first) {
first = false;
ksName = spec.ksName;
tableName = spec.tableName;
} else if (!Objects.equals(spec.ksName, ksName)
|| !Objects.equals(spec.tableName, tableName)) {
return false;
}
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy