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

io.deephaven.server.table.ops.JoinTablesGrpcImpl Maven / Gradle / Ivy

The newest version!
//
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
//
package io.deephaven.server.table.ops;

import com.google.rpc.Code;
import io.deephaven.api.AsOfJoinMatch;
import io.deephaven.api.AsOfJoinRule;
import io.deephaven.api.expression.ExpressionException;
import io.deephaven.auth.codegen.impl.TableServiceContextualAuthWiring;
import io.deephaven.base.verify.Assert;
import io.deephaven.engine.table.Table;
import io.deephaven.engine.table.impl.MatchPair;
import io.deephaven.engine.table.impl.select.MatchPairFactory;
import io.deephaven.proto.backplane.grpc.AsOfJoinTablesRequest;
import io.deephaven.proto.backplane.grpc.AsOfJoinTablesRequest.MatchRule;
import io.deephaven.proto.backplane.grpc.BatchTableRequest;
import io.deephaven.proto.backplane.grpc.CrossJoinTablesRequest;
import io.deephaven.proto.backplane.grpc.ExactJoinTablesRequest;
import io.deephaven.proto.backplane.grpc.LeftJoinTablesRequest;
import io.deephaven.proto.backplane.grpc.NaturalJoinTablesRequest;
import io.deephaven.proto.backplane.grpc.Ticket;
import io.deephaven.proto.util.Exceptions;
import io.deephaven.server.session.SessionState;
import io.grpc.StatusRuntimeException;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public abstract class JoinTablesGrpcImpl extends GrpcTableOperation {
    @FunctionalInterface
    protected interface RealTableOperation {
        Table apply(Table lhs, Table rhs, MatchPair[] columnsToMatch, MatchPair[] columnsToAdd, T request);
    }

    private final Function> getColMatchList;
    private final Function> getColAddList;
    private final RealTableOperation realTableOperation;

    protected JoinTablesGrpcImpl(
            final PermissionFunction permission,
            final Function getRequest,
            final Function getTicket,
            final MultiDependencyFunction getDependencies,
            final Function> getColMatchList,
            final Function> getColAddList,
            final RealTableOperation realTableOperation) {
        super(permission, getRequest, getTicket, getDependencies);
        this.getColMatchList = getColMatchList;
        this.getColAddList = getColAddList;
        this.realTableOperation = realTableOperation;
    }

    @Override
    public void validateRequest(final T request) throws StatusRuntimeException {
        try {
            MatchPairFactory.getExpressions(getColMatchList.apply(request));
            MatchPairFactory.getExpressions(getColAddList.apply(request));
        } catch (final ExpressionException err) {
            throw Exceptions.statusRuntimeException(Code.INVALID_ARGUMENT,
                    err.getMessage() + ": " + err.getProblemExpression());
        }
    }

    @Override
    public Table create(final T request, final List> sourceTables) {
        Assert.eq(sourceTables.size(), "sourceTables.size()", 2);

        final MatchPair[] columnsToMatch;
        final MatchPair[] columnsToAdd;

        try {
            columnsToMatch = MatchPairFactory.getExpressions(getColMatchList.apply(request));
            columnsToAdd = MatchPairFactory.getExpressions(getColAddList.apply(request));
        } catch (final ExpressionException err) {
            throw Exceptions.statusRuntimeException(Code.INVALID_ARGUMENT,
                    err.getMessage() + ": " + err.getProblemExpression());
        }

        final Table lhs = sourceTables.get(0).get();
        final Table rhs = sourceTables.get(1).get();

        final Table result;
        if (!lhs.isRefreshing() && !rhs.isRefreshing()) {
            result = realTableOperation.apply(lhs, rhs, columnsToMatch, columnsToAdd, request);
        } else {
            result = lhs.getUpdateGraph(rhs).sharedLock()
                    .computeLocked(() -> realTableOperation.apply(lhs, rhs, columnsToMatch, columnsToAdd, request));
        }
        return result;
    }

    @Singleton
    @Deprecated
    public static class AsOfJoinTablesGrpcImpl extends JoinTablesGrpcImpl {

        private static final MultiDependencyFunction EXTRACT_DEPS =
                (request) -> List.of(request.getLeftId(), request.getRightId());

        @Inject
        protected AsOfJoinTablesGrpcImpl(final TableServiceContextualAuthWiring authWiring) {
            super(authWiring::checkPermissionAsOfJoinTables,
                    BatchTableRequest.Operation::getAsOfJoin, AsOfJoinTablesRequest::getResultId,
                    EXTRACT_DEPS,
                    AsOfJoinTablesRequest::getColumnsToMatchList, AsOfJoinTablesRequest::getColumnsToAddList,
                    AsOfJoinTablesGrpcImpl::doJoin);
        }

        @Override
        public void validateRequest(final AsOfJoinTablesRequest request) throws StatusRuntimeException {
            super.validateRequest(request);

            if (request.getAsOfMatchRule() == AsOfJoinTablesRequest.MatchRule.UNRECOGNIZED) {
                throw Exceptions.statusRuntimeException(Code.INVALID_ARGUMENT, "Unrecognized as-of match rule");
            }
        }

        public static Table doJoin(final Table lhs, final Table rhs,
                final MatchPair[] columnsToMatch, final MatchPair[] columnsToAdd,
                final AsOfJoinTablesRequest request) {
            final MatchPair joinMatch = columnsToMatch[columnsToMatch.length - 1];
            return lhs.asOfJoin(
                    rhs,
                    Arrays.asList(columnsToMatch).subList(0, columnsToMatch.length - 1),
                    AsOfJoinMatch.of(joinMatch.left(), adapt(request.getAsOfMatchRule()), joinMatch.right()),
                    Arrays.asList(columnsToAdd));
        }

        private static AsOfJoinRule adapt(MatchRule rule) {
            // Note: this is _correct_ to maintain backwards compatibility but it looks wrong. This is why the
            // underlying proto and this class are now deprecated.
            switch (rule) {
                case LESS_THAN_EQUAL:
                    return AsOfJoinRule.GREATER_THAN_EQUAL;
                case LESS_THAN:
                    return AsOfJoinRule.GREATER_THAN;
                case GREATER_THAN_EQUAL:
                    return AsOfJoinRule.LESS_THAN_EQUAL;
                case GREATER_THAN:
                    return AsOfJoinRule.LESS_THAN;
                default:
                    throw new RuntimeException("Unsupported join type: " + rule);
            }
        }
    }

    @Singleton
    public static class CrossJoinTablesGrpcImpl extends JoinTablesGrpcImpl {

        private static final MultiDependencyFunction EXTRACT_DEPS =
                (request) -> List.of(request.getLeftId(), request.getRightId());

        @Inject
        public CrossJoinTablesGrpcImpl(final TableServiceContextualAuthWiring authWiring) {
            super(authWiring::checkPermissionCrossJoinTables,
                    BatchTableRequest.Operation::getCrossJoin, CrossJoinTablesRequest::getResultId,
                    EXTRACT_DEPS,
                    CrossJoinTablesRequest::getColumnsToMatchList, CrossJoinTablesRequest::getColumnsToAddList,
                    CrossJoinTablesGrpcImpl::doJoin);
        }

        public static Table doJoin(final Table lhs, final Table rhs,
                final MatchPair[] columnsToMatch, final MatchPair[] columnsToAdd,
                final CrossJoinTablesRequest request) {
            final List match = Arrays.asList(columnsToMatch);
            final List add = Arrays.asList(columnsToAdd);
            int reserveBits = request.getReserveBits();
            if (reserveBits <= 0) {
                return lhs.join(rhs, match, add); // use the default number of reserve_bits
            } else {
                return lhs.join(rhs, match, add, reserveBits);
            }
        }
    }

    @Singleton
    public static class ExactJoinTablesGrpcImpl extends JoinTablesGrpcImpl {

        private static final MultiDependencyFunction EXTRACT_DEPS =
                (request) -> List.of(request.getLeftId(), request.getRightId());

        @Inject
        public ExactJoinTablesGrpcImpl(final TableServiceContextualAuthWiring authWiring) {
            super(authWiring::checkPermissionExactJoinTables,
                    BatchTableRequest.Operation::getExactJoin, ExactJoinTablesRequest::getResultId,
                    EXTRACT_DEPS,
                    ExactJoinTablesRequest::getColumnsToMatchList, ExactJoinTablesRequest::getColumnsToAddList,
                    ExactJoinTablesGrpcImpl::doJoin);
        }

        public static Table doJoin(final Table lhs, final Table rhs,
                final MatchPair[] columnsToMatch, final MatchPair[] columnsToAdd,
                final ExactJoinTablesRequest request) {
            return lhs.exactJoin(rhs, Arrays.asList(columnsToMatch), Arrays.asList(columnsToAdd));
        }
    }

    @Singleton
    public static class LeftJoinTablesGrpcImpl extends JoinTablesGrpcImpl {

        private static final MultiDependencyFunction EXTRACT_DEPS =
                (request) -> List.of(request.getLeftId(), request.getRightId());

        @Inject
        public LeftJoinTablesGrpcImpl(final TableServiceContextualAuthWiring authWiring) {
            super(authWiring::checkPermissionLeftJoinTables,
                    BatchTableRequest.Operation::getLeftJoin, LeftJoinTablesRequest::getResultId,
                    EXTRACT_DEPS,
                    LeftJoinTablesRequest::getColumnsToMatchList, LeftJoinTablesRequest::getColumnsToAddList,
                    LeftJoinTablesGrpcImpl::doJoin);
        }

        public static Table doJoin(final Table lhs, final Table rhs,
                final MatchPair[] columnsToMatch, final MatchPair[] columnsToAdd,
                final LeftJoinTablesRequest request) {
            throw Exceptions.statusRuntimeException(Code.UNIMPLEMENTED, "LeftJoinTables is currently unimplemented");
        }
    }

    @Singleton
    public static class NaturalJoinTablesGrpcImpl extends JoinTablesGrpcImpl {

        private static final MultiDependencyFunction EXTRACT_DEPS =
                (request) -> List.of(request.getLeftId(), request.getRightId());

        @Inject
        public NaturalJoinTablesGrpcImpl(final TableServiceContextualAuthWiring authWiring) {
            super(authWiring::checkPermissionNaturalJoinTables,
                    BatchTableRequest.Operation::getNaturalJoin, NaturalJoinTablesRequest::getResultId,
                    EXTRACT_DEPS,
                    NaturalJoinTablesRequest::getColumnsToMatchList, NaturalJoinTablesRequest::getColumnsToAddList,
                    NaturalJoinTablesGrpcImpl::doJoin);
        }

        public static Table doJoin(final Table lhs, final Table rhs,
                final MatchPair[] columnsToMatch, final MatchPair[] columnsToAdd,
                final NaturalJoinTablesRequest request) {
            return lhs.naturalJoin(rhs, Arrays.asList(columnsToMatch), Arrays.asList(columnsToAdd));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy