All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.ytsaurus.client.ApiServiceUtil Maven / Gradle / Ivy

The newest version!
package tech.ytsaurus.client;

import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.function.Function;

import com.google.protobuf.ByteString;
import tech.ytsaurus.client.rows.ConsumerSource;
import tech.ytsaurus.client.rows.UnversionedRowset;
import tech.ytsaurus.client.rows.UnversionedRowsetDeserializer;
import tech.ytsaurus.client.rows.UnversionedValue;
import tech.ytsaurus.client.rows.VersionedRowset;
import tech.ytsaurus.client.rows.VersionedRowsetDeserializer;
import tech.ytsaurus.client.rows.WireProtocol;
import tech.ytsaurus.client.rows.WireProtocolReader;
import tech.ytsaurus.client.rows.WireRowsetDeserializer;
import tech.ytsaurus.client.rows.WireVersionedRowsetDeserializer;
import tech.ytsaurus.core.rows.YTreeRowSerializer;
import tech.ytsaurus.core.tables.ColumnSchema;
import tech.ytsaurus.core.tables.ColumnSortOrder;
import tech.ytsaurus.core.tables.ColumnValueType;
import tech.ytsaurus.core.tables.TableSchema;
import tech.ytsaurus.rpcproxy.ERowsetKind;
import tech.ytsaurus.rpcproxy.TColumnSchema;
import tech.ytsaurus.rpcproxy.TRowsetDescriptor;
import tech.ytsaurus.rpcproxy.TTableSchema;
import tech.ytsaurus.typeinfo.TiType;
import tech.ytsaurus.typeinfo.TypeIO;

public class ApiServiceUtil {
    public static final long MICROS_PER_SECOND = 1_000_000L;

    private ApiServiceUtil() {
    }

    /**
     * Конвертирует исходные сырые значения в значения колонок по указанной схеме
     */
    public static void convertKeyColumns(
            List row,
            TableSchema schema,
            List values,
            boolean allowMissingColumns,
            SerializationResolver serializationResolver
    ) {
        int columnsCount = schema.getKeyColumnsCount();
        if (allowMissingColumns && values.size() < columnsCount) {
            columnsCount = values.size();
        }
        for (int id = 0; id < columnsCount; ++id) {
            ColumnSchema column = schema.getColumns().get(id);
            ColumnValueType type = column.getType();
            Object value = UnversionedValue.convertValueTo(values.get(id), type, serializationResolver);
            if (value == null) {
                type = ColumnValueType.NULL;
            }
            row.add(new UnversionedValue(id, type, false, value));
        }
    }

    public static void convertKeyColumns(
            List row,
            TableSchema schema,
            List values,
            SerializationResolver serializationResolver
    ) {
        convertKeyColumns(row, schema, values, false, serializationResolver);
    }

    public static void convertValueColumns(
            List row,
            TableSchema schema,
            List values,
            boolean skipMissingValues,
            boolean aggregate,
            SerializationResolver serializationResolver
    ) {
        for (int id = schema.getKeyColumnsCount(); id < schema.getColumns().size() && id < values.size(); ++id) {
            ColumnSchema column = schema.getColumns().get(id);
            Object inputValue = values.get(id);
            if (inputValue == null && skipMissingValues) {
                continue;
            }
            ColumnValueType type = column.getType();
            Object value = UnversionedValue.convertValueTo(inputValue, type, serializationResolver);
            if (value == null) {
                type = ColumnValueType.NULL;
            }
            row.add(new UnversionedValue(id, type, aggregate, value));
        }
    }

    public static TTableSchema serializeTableSchema(TableSchema schema) {
        TTableSchema.Builder builder = TTableSchema.newBuilder();
        builder.setUniqueKeys(schema.isUniqueKeys());

        for (ColumnSchema columnSchema : schema.getColumns()) {
            TColumnSchema.Builder columnBuilder = TColumnSchema.newBuilder();

            String name = columnSchema.getName();
            ColumnValueType type = columnSchema.getType();
            TiType typeV3 = columnSchema.getTypeV3();
            ColumnSortOrder sortOrder = columnSchema.getSortOrder();
            String aggregate = columnSchema.getAggregate();
            String lock = columnSchema.getLock();
            String expression = columnSchema.getExpression();
            String group = columnSchema.getGroup();

            columnBuilder.setName(name);
            columnBuilder.setType(type.getValue());
            columnBuilder.setTypeV3(ByteString.copyFromUtf8(TypeIO.serializeToTextYson(typeV3)));
            columnBuilder.setRequired(columnSchema.isRequired());
            if (sortOrder != null) {
                columnBuilder.setSortOrder(sortOrder.getId());
            }
            if (aggregate != null) {
                columnBuilder.setAggregate(aggregate);
            }
            if (lock != null) {
                columnBuilder.setLock(lock);
            }
            if (expression != null) {
                columnBuilder.setExpression(expression);
            }
            if (group != null) {
                columnBuilder.setGroup(group);
            }

            builder.addColumns(columnBuilder.build());
        }

        return builder.build();
    }

    public static TableSchema deserializeTableSchema(TTableSchema schema) {
        TableSchema.Builder builder = new TableSchema.Builder().setUniqueKeys(schema.getUniqueKeys());

        for (TColumnSchema columnSchema : schema.getColumnsList()) {
            String name = columnSchema.getName();

            ColumnSchema.Builder columnBuilder;

            ColumnValueType type = ColumnValueType.NULL;
            if (columnSchema.hasType()) {
                type = ColumnValueType.fromValue(columnSchema.getType());
            }
            boolean required = columnSchema.getRequired();

            TiType typeV3 = null;
            if (columnSchema.hasTypeV3()) {
                typeV3 = TypeIO.parseYson(columnSchema.getTypeV3().toByteArray());
            }

            if (typeV3 != null) {
                columnBuilder = ColumnSchema.builder(name, typeV3);
            } else {
                columnBuilder = ColumnSchema.builder(name, type, required);
            }

            if (columnSchema.hasSortOrder()) {
                columnBuilder.setSortOrder(ColumnSortOrder.fromId(columnSchema.getSortOrder()));
            }

            if (columnSchema.hasAggregate()) {
                columnBuilder.setAggregate(columnSchema.getAggregate());
            }

            if (columnSchema.hasLock()) {
                columnBuilder.setLock(columnSchema.getLock());
            }

            if (columnSchema.hasExpression()) {
                columnBuilder.setExpression(columnSchema.getExpression());
            }

            if (columnSchema.hasGroup()) {
                columnBuilder.setGroup(columnSchema.getGroup());
            }

            builder.add(columnBuilder.build());
        }

        return builder.build();
    }

    public static TableSchema deserializeRowsetSchema(TRowsetDescriptor descriptor) {
        if (descriptor.hasSchema()) {
            return deserializeTableSchema(descriptor.getSchema());
        }
        TableSchema.Builder builder = new TableSchema.Builder().setUniqueKeys(false);
        for (TRowsetDescriptor.TNameTableEntry entry : descriptor.getNameTableEntriesList()) {
            String name = "";
            if (entry.hasName()) {
                name = entry.getName();
            }
            ColumnValueType type = ColumnValueType.NULL;
            if (entry.hasType()) {
                type = ColumnValueType.fromValue(entry.getType());
            }
            builder.addValue(name, type);
        }
        return builder.build();
    }

    public static  void deserializeUnversionedRowset(
            TRowsetDescriptor descriptor,
            List attachments,
            YTreeRowSerializer serializer,
            ConsumerSource consumer,
            SerializationResolver serializationResolver
    ) {
        deserializeUnversionedRowset(descriptor, attachments,
                schema -> serializationResolver.createWireRowDeserializer(schema, serializer, consumer));
    }

    public static UnversionedRowset deserializeUnversionedRowset(
            TRowsetDescriptor descriptor,
            List attachments
    ) {
        return deserializeUnversionedRowset(descriptor, attachments, UnversionedRowsetDeserializer::new).getRowset();
    }

    public static void validateRowsetDescriptor(TRowsetDescriptor descriptor) {
        if (descriptor.getWireFormatVersion() != WireProtocol.WIRE_FORMAT_VERSION) {
            throw new IllegalStateException("Cannot deserialize wire format" + descriptor.getWireFormatVersion() + ": "
                    + WireProtocol.WIRE_FORMAT_VERSION + " is required");
        }
        if (descriptor.getRowsetKind() != ERowsetKind.RK_UNVERSIONED) {
            throw new IllegalStateException(
                    "Cannot deserialize " + descriptor.getRowsetKind() + ": UNVERSIONED is required");
        }
    }

    private static , T> B deserializeUnversionedRowset(
            TRowsetDescriptor descriptor,
            List attachments,
            Function deserializerFunction
    ) {
        validateRowsetDescriptor(descriptor);
        final B deserializer = deserializerFunction.apply(deserializeRowsetSchema(descriptor));
        return new WireProtocolReader(attachments).readUnversionedRowset(deserializer);
    }

    public static VersionedRowset deserializeVersionedRowset(TRowsetDescriptor descriptor, List attachments) {
        return deserializeVersionedRowset(descriptor, attachments, VersionedRowsetDeserializer::new).getRowset();
    }

    private static , T> B deserializeVersionedRowset(
            TRowsetDescriptor descriptor,
            List attachments,
            Function deserializerFunction
    ) {
        if (descriptor.getWireFormatVersion() != WireProtocol.WIRE_FORMAT_VERSION) {
            throw new IllegalStateException("Cannot deserialize wire format" + descriptor.getWireFormatVersion() + ": "
                    + WireProtocol.WIRE_FORMAT_VERSION + " is required");
        }
        if (descriptor.getRowsetKind() != ERowsetKind.RK_VERSIONED) {
            throw new IllegalStateException(
                    "Cannot deserialize " + descriptor.getRowsetKind() + ": VERSIONED is required");
        }
        final B deserializer = deserializerFunction.apply(deserializeRowsetSchema(descriptor));
        return new WireProtocolReader(attachments).readVersionedRowset(deserializer);
    }

    public static TRowsetDescriptor makeRowsetDescriptor(TableSchema schema) {
        TRowsetDescriptor.Builder builder = TRowsetDescriptor.newBuilder();
        builder.setWireFormatVersion(WireProtocol.WIRE_FORMAT_VERSION);
        builder.setRowsetKind(ERowsetKind.RK_UNVERSIONED);
        for (ColumnSchema column : schema.getColumns()) {
            builder.addNameTableEntriesBuilder()
                    .setName(column.getName())
                    .setType(column.getType().getValue());
        }
        return builder.build();
    }

    public static long durationToYtMicros(Duration duration) {
        long micros = Math.multiplyExact(duration.getSeconds(), MICROS_PER_SECOND);
        micros = Math.addExact(micros, duration.getNano() / 1000);
        return micros;
    }

    public static long instantToYtMicros(Instant instant) {
        return Math.multiplyExact(instant.toEpochMilli(), 1000L);
    }
}