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

io.deephaven.engine.table.impl.StaticNaturalJoinStateManager Maven / Gradle / Ivy

There is a newer version: 0.37.1
Show newest version
/**
 * Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending
 */
package io.deephaven.engine.table.impl;

import io.deephaven.engine.rowset.RowSequence;
import io.deephaven.engine.rowset.RowSet;
import io.deephaven.engine.table.ColumnSource;
import io.deephaven.engine.table.impl.sources.LongArraySource;
import io.deephaven.engine.table.impl.sources.LongSparseArraySource;
import io.deephaven.engine.table.impl.util.*;

import java.util.Arrays;
import java.util.Objects;
import java.util.function.LongUnaryOperator;
import java.util.stream.Collectors;

public abstract class StaticNaturalJoinStateManager {
    public static final long DUPLICATE_RIGHT_VALUE = -2;
    public static final long NO_RIGHT_ENTRY_VALUE = RowSequence.NULL_ROW_KEY;

    protected final ColumnSource[] keySourcesForErrorMessages;

    protected StaticNaturalJoinStateManager(ColumnSource[] keySourcesForErrorMessages) {
        this.keySourcesForErrorMessages = keySourcesForErrorMessages;
    }

    @SuppressWarnings("WeakerAccess")
    public void checkExactMatch(boolean exactMatch, long leftKeyIndex, long rightSide) {
        if (exactMatch && rightSide == NO_RIGHT_ENTRY_VALUE) {
            throw new RuntimeException("Tables don't have one-to-one mapping - no mappings for key " + extractKeyStringFromSourceTable(leftKeyIndex) + ".");
        }
    }

    // produce a pretty key for error messages
    protected String extractKeyStringFromSourceTable(long leftKey) {
        if (keySourcesForErrorMessages.length == 1) {
            return Objects.toString(keySourcesForErrorMessages[0].get(leftKey));
        }
        return "[" + Arrays.stream(keySourcesForErrorMessages).map(ls -> Objects.toString(ls.get(leftKey))).collect(Collectors.joining(", ")) + "]";
    }

    public WritableRowRedirection buildRowRedirection(QueryTable leftTable, boolean exactMatch, LongUnaryOperator rightSideFromSlot, JoinControl.RedirectionType redirectionType) {
        switch (redirectionType) {
            case Contiguous: {
                if (!leftTable.isFlat()) {
                    throw new IllegalStateException("Left table is not flat for contiguous row redirection build!");
                }
                // we can use an array, which is perfect for a small enough flat table
                final long[] innerIndex = new long[leftTable.intSize("contiguous redirection build")];
                for (int ii = 0; ii < innerIndex.length; ++ii) {
                    final long rightSide = rightSideFromSlot.applyAsLong(ii);
                    checkExactMatch(exactMatch, leftTable.getRowSet().get(ii), rightSide);
                    innerIndex[ii] = rightSide;
                }
                return new ContiguousWritableRowRedirection(innerIndex);
            }
            case Sparse: {
                final LongSparseArraySource sparseRedirections = new LongSparseArraySource();

                long leftPosition = 0;
                for (final RowSet.Iterator it = leftTable.getRowSet().iterator(); it.hasNext(); ) {
                    final long next = it.nextLong();
                    final long rightSide = rightSideFromSlot.applyAsLong(leftPosition++);
                    checkExactMatch(exactMatch, leftTable.getRowSet().get(next), rightSide);
                    if (rightSide != NO_RIGHT_ENTRY_VALUE) {
                        sparseRedirections.set(next, rightSide);
                    }
                }
                return new LongColumnSourceWritableRowRedirection(sparseRedirections);
            }
            case Hash: {
                final WritableRowRedirection rowRedirection = WritableRowRedirectionLockFree.FACTORY.createRowRedirection(leftTable.intSize());

                long leftPosition = 0;
                for (final RowSet.Iterator it = leftTable.getRowSet().iterator(); it.hasNext(); ) {
                    final long next = it.nextLong();
                    final long rightSide = rightSideFromSlot.applyAsLong(leftPosition++);
                    checkExactMatch(exactMatch, leftTable.getRowSet().get(next), rightSide);
                    if (rightSide != NO_RIGHT_ENTRY_VALUE) {
                        rowRedirection.put(next, rightSide);
                    }
                }

                return rowRedirection;
            }
        }
        throw new IllegalStateException("Bad redirectionType: " + redirectionType);
    }

    protected abstract void decorateLeftSide(RowSet leftRowSet, ColumnSource[] leftSources, final LongArraySource leftRedirections);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy