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

oracle.kv.impl.query.compiler.ExprReceive Maven / Gradle / Ivy

/*-
 * Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle NoSQL
 * Database made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle NoSQL Database for a copy of the license and
 * additional information.
 */

package oracle.kv.impl.query.compiler;


import java.util.ArrayList;

import oracle.kv.impl.api.query.PreparedStatementImpl.DistributionKind;
import oracle.kv.impl.api.table.IndexKeyImpl;
import oracle.kv.impl.api.table.PrimaryKeyImpl;

import oracle.kv.impl.query.types.ExprType;


/**
 * This expr is used to mark the boundaries between parts of the query that
 * execute on different "machines". The receive expr itself executes at a
 * "client machine" and its child subplan executes at a "server machine".
 * The child subplan may actually be replicated on several server machines,
 * in which case the receive expr acts as a UNION ALL expr, collecting and
 * propagating the results it receives from its children. Furthermore, the
 * receive expr may perform a merge-sort over its inputs (if the inputs
 * return sorted results).
 *
 * Receive exprs are always created as parents of the BaseTable exprs in the
 * exprs graph, After their creation, Receive exprs are pulled-up as far as
 * they can go. All this is done by the Distributer class.
 *
 * theInput:
 * The expr producing the input to this receive expr.
 *
 * theEliminateIndexDups:
 * Whether or not to eliminate index dups. These are duplicate results that
 * may be generated during the scan of a multikey (array/map) index.
 *
 * thePrimKeyPositions:
 * The positions of the primary key columns in the RecordValues received
 * from the servers. This is non-null only if the ReceiveIter must do
 * elimination of index duplicates.
 */
class ExprReceive extends Expr {

    private Expr theInput;

    private int[] theSortFieldPositions;

    private SortSpec[] theSortSpecs;

    private DistributionKind theDistributionKind;

    private PrimaryKeyImpl thePrimaryKey;

    private ArrayList thePushedExternals;

    private boolean theEliminateIndexDups;

    private int[] thePrimKeyPositions;

     private boolean theIsUpdate;

    ExprReceive(QueryControlBlock qcb, StaticContext sctx) {
        super(qcb, sctx, ExprKind.RECEIVE, null);
    }

    @Override
    int getNumChildren() {
        return 1;
    }

    @Override
    Expr getInput() {
        return theInput;
    }

    void setInput(Expr newExpr, boolean destroy) {
        if (theInput != null) {
            theInput.removeParent(this, destroy);
        }
        theInput = newExpr;
        theInput.addParent(this);
        theType = computeType();
        computeDistributionKind();
        setLocation(newExpr.getLocation());
    }

    void computeDistributionKind() {

        if (theInput.getKind() != ExprKind.BASE_TABLE) {
            return;
        }

        ExprBaseTable tableExpr = (ExprBaseTable)theInput;

        ArrayList primKeys = tableExpr.getPrimaryKeys();
        ArrayList secKeys = tableExpr.getSecondaryKeys();

        if (secKeys != null) {
            theDistributionKind = DistributionKind.ALL_SHARDS;

        } else if (primKeys != null &&
                   primKeys.size() == 1 && // this is always true, for now
                   primKeys.get(0).hasShardKey()) {
            theDistributionKind = DistributionKind.SINGLE_PARTITION;
            thePrimaryKey = primKeys.get(0);

            if (tableExpr.getPushedExternals() != null) {
                thePushedExternals =
                    new ArrayList(tableExpr.getPushedExternals());

                /* Remove entries associated with a range, if any */
                if (tableExpr.getRanges().get(0) != null) {
                    thePushedExternals.remove(thePushedExternals.size() - 1);
                    thePushedExternals.remove(thePushedExternals.size() - 1);
                }
            }
        } else {
            // TODO: handle the case of multiple prim keys, when it arises
            // TODO : MULTI_PARTITTIONS distribution kind
            theDistributionKind = DistributionKind.ALL_PARTITIONS;
        }
    }

    DistributionKind getDistributionKind() {
        return theDistributionKind;
    }

    PrimaryKeyImpl getPrimaryKey() {
        return thePrimaryKey;
    }

    ArrayList getPushedExternals() {
        return thePushedExternals;
    }

    void addSort(int[] sortExprPositions, SortSpec[] specs) {
        theSortFieldPositions = sortExprPositions;
        theSortSpecs = specs;
        theType = computeType();
    }

    int[] getSortFieldPositions() {
        return theSortFieldPositions;
    }

    SortSpec[] getSortSpecs() {
        return theSortSpecs;
    }

    void setEliminateIndexDups(boolean v) {
        theEliminateIndexDups = v;
    }

    boolean getEliminateIndexDups() {
        return theEliminateIndexDups;
    }

    void setIsUpdate(boolean v) {
        theIsUpdate = v;
    }

    boolean getIsUpdate() {
        return theIsUpdate;
    }

    void addPrimKeyPositions(int[] positions) {
        thePrimKeyPositions = positions;
        theType = computeType();
    }

    int[] getPrimKeyPositions() {
        return thePrimKeyPositions;
    }

    @Override
    ExprType computeType() {
        return theInput.getType();
    }

    @Override
    public boolean mayReturnNULL() {
        return theInput.mayReturnNULL();
    }

    @Override
    void displayContent(StringBuilder sb, QueryFormatter formatter) {

        formatter.indent(sb);
        sb.append("DistributionKind : ").append(theDistributionKind);
        sb.append(",\n");
        if (thePrimaryKey != null) {
            formatter.indent(sb);
            sb.append("PrimaryKey :").append(thePrimaryKey);
            sb.append(",\n");
        }
        if (theSortFieldPositions != null) {
            formatter.indent(sb);
            sb.append("Sort Field Positions : ").append(theSortFieldPositions);
            sb.append(",\n");
        }
        if (thePrimKeyPositions != null) {
            formatter.indent(sb);
            sb.append("Primary Key Positions : ");
            for (int i = 0; i < thePrimKeyPositions.length; ++i) {
                sb.append(thePrimKeyPositions[i]);
                if (i < thePrimKeyPositions.length - 1) {
                    sb.append(", ");
                }
            }
            sb.append(",\n");
        }
        formatter.indent(sb);
        theInput.display(sb, formatter);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy