<commit_before>/**
 * Copyright (C) 2009-2013 Akiban Technologies, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.akiban.qp.operator;

import com.akiban.qp.row.ProductRow;
import com.akiban.qp.row.Row;
import com.akiban.qp.rowtype.ProductRowType;
import com.akiban.qp.rowtype.RowType;
import com.akiban.qp.rowtype.UserTableRowType;
import com.akiban.server.explain.*;
import com.akiban.util.ArgumentValidation;
import com.akiban.util.ShareHolder;
import com.akiban.util.tap.InOutTap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**

 <h1>Overview</h1>

 Product_Nested computes the cartesian product of child rows owned by the same parent row. For example, if customer c1 has orders o10 and o11, and addresses a10 and a11; and customer c2 has order o20 and address a20, then Product_NestedLoops computes \{o10, o11\} x \{a10, a11\} for c1, and \{o20\} x \{a20\} for c2.

 <h1>Arguments</h1>

 <ul>

 <li><b>RowType outerType:</b> Type of one child row. parent rows to be
 flattened.

 <li><b>UserTableRowType branchType:</b> Ancestor type of outerType and inputType. Output will consist
 of the cartesian product of outer and input rows that match when projected to the branch type.

 <li><b>RowType inputType:</b> Type of the other child row.

 <li><b>int bindingPosition:</b> The position in the bindings that
 will be used to pass rows from the outer loop to the inner loop.

 </ul>

 The row types must have resulted from Flattens of some common
 ancestor, e.g. Flatten(customer, order) and Flatten(customer,
 address).

 <h1>Behavior</h1>

 Suppose we have a COA schema (C is the parent of O and A), and that we
 have flattened C with O, and C with A. Product_Nested has two
 input streams, with CO in one and CA in the other. The branch type is C.
 For this discussion, let's assume that CO is the outer stream, and CA is in the
 input stream.

 For each CO row from the outer stream, a set of matching CA rows,
 (i.e., matching in C)
 from the input stream are retrieved. The CO row and all of the
 CA rows will have the same customer primary key. Product_Nested
 will write to the output stream product rows for each CO/CA
 combination.

 <h1>Output</h1>

 For CO/CA input streams, the format of an output row is (C, O, A),
 i.e., all the customer fields, followed by all the order fields,
 followed by all the address fields.

 Product rows do not have an hkey.

 <h1>Assumptions</h1>

 None.

 <h1>Performance</h1>

 Product_Nested does no IO.

 */

class Product_Nested extends Operator
{
    // Object interface

    @Override
    public String toString()
    {
        return String.format("%s(%s x %s)", getClass().getSimpleName(), outerType, inputType);
    }

    @Override
    public CompoundExplainer getExplainer(ExplainContext context)
    {
        Attributes atts = new Attributes();
        
        atts.put(Label.NAME, PrimitiveExplainer.getInstance(getName()));
        atts.put(Label.OUTER_TYPE, outerType.getExplainer(context));
        atts.put(Label.INNER_TYPE, inputType.getExplainer(context));
        atts.put(Label.INPUT_OPERATOR, inputOperator.getExplainer(context));
        atts.put(Label.BINDING_POSITION, PrimitiveExplainer.getInstance(bindingPosition));
        return new CompoundExplainer(Type.PRODUCT_OPERATOR, atts);
    }
    
    // Operator interface

    @Override
    protected Cursor cursor(QueryContext context, QueryBindingsCursor bindingsCursor)
    {
        return new Execution(context, inputOperator.cursor(context, bindingsCursor));
    }

    @Override
    public ProductRowType rowType()
    {
        return productType;
    }

    @Override
    public void findDerivedTypes(Set<RowType> derivedTypes)
    {
        inputOperator.findDerivedTypes(derivedTypes);
        derivedTypes.add(productType);
    }

    @Override
    public List<Operator> getInputOperators()
    {
        List<Operator> result = new ArrayList<>(2);
        result.add(inputOperator);
        return result;
    }

    @Override
    public String describePlan()
    {
        return describePlan(inputOperator);
    }

    // Product_Nested interface

    public Product_Nested(Operator inputOperator,
                          RowType outerType,
                          UserTableRowType branchType,
                          RowType inputType,
                          int bindingPosition)
    {
        ArgumentValidation.notNull("inputOperator", inputOperator);
        ArgumentValidation.notNull("outerType", outerType);
        ArgumentValidation.notNull("inputType", inputType);
        ArgumentValidation.isGTE("bindingPosition", bindingPosition, 0);
        this.inputOperator = inputOperator;
        this.outerType = outerType;
        this.inputType = inputType;
        this.productType = inputType.schema().newProductType(outerType, branchType, inputType);
        this.branchType = productType.branchType();
        this.bindingPosition = bindingPosition;
    }

    // Class state

    private static InOutTap TAP_OPEN = OPERATOR_TAP.createSubsidiaryTap("operator: Product_Nested open");
    private static InOutTap TAP_NEXT = OPERATOR_TAP.createSubsidiaryTap("operator: Product_Nested next");
    private static final Logger LOG = LoggerFactory.getLogger(Product_Nested.class);

    // Object state

    private final Operator inputOperator;
    private final RowType branchType;
    private final RowType outerType;
    private final RowType inputType;
    private final ProductRowType productType;
    private final int bindingPosition;

    // Inner classes

    private class Execution extends ChainedCursor
    {
        // Cursor interface

        @Override
        public Row next()
        {
            if (TAP_NEXT_ENABLED) {
                TAP_NEXT.in();
            }
            try {
                if (CURSOR_LIFECYCLE_ENABLED) {
                    CursorLifecycle.checkIdleOrActive(this);
                }
                checkQueryCancelation();
                Row row = input.next();
                if ((row != null) && (row.rowType() == inputType)) {
                    row = new ProductRow(productType, bindings.getRow(bindingPosition), row);
                }
                if (LOG_EXECUTION) {
                    LOG.debug("Product_Nested: yield {}", row);
                }
                return row;
            } finally {
                if (TAP_NEXT_ENABLED) {
                    TAP_NEXT.out();
                }
            }
        }

        // Execution interface

        Execution(QueryContext context, Cursor input)
        {
            super(context, input);
        }
    }
}
<commit_msg>Missed one.<commit_after>/**
 * Copyright (C) 2009-2013 Akiban Technologies, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.akiban.qp.operator;

import com.akiban.qp.row.ProductRow;
import com.akiban.qp.row.Row;
import com.akiban.qp.rowtype.ProductRowType;
import com.akiban.qp.rowtype.RowType;
import com.akiban.qp.rowtype.UserTableRowType;
import com.akiban.server.explain.*;
import com.akiban.util.ArgumentValidation;
import com.akiban.util.ShareHolder;
import com.akiban.util.tap.InOutTap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**

 <h1>Overview</h1>

 Product_Nested computes the cartesian product of child rows owned by the same parent row. For example, if customer c1 has orders o10 and o11, and addresses a10 and a11; and customer c2 has order o20 and address a20, then Product_Nested computes \{o10, o11\} x \{a10, a11\} for c1, and \{o20\} x \{a20\} for c2.

 <h1>Arguments</h1>

 <ul>

 <li><b>RowType outerType:</b> Type of one child row. parent rows to be
 flattened.

 <li><b>UserTableRowType branchType:</b> Ancestor type of outerType and inputType. Output will consist
 of the cartesian product of outer and input rows that match when projected to the branch type.

 <li><b>RowType inputType:</b> Type of the other child row.

 <li><b>int bindingPosition:</b> The position in the bindings that
 will be used to pass rows from the outer loop to the inner loop.

 </ul>

 The row types must have resulted from Flattens of some common
 ancestor, e.g. Flatten(customer, order) and Flatten(customer,
 address).

 <h1>Behavior</h1>

 Suppose we have a COA schema (C is the parent of O and A), and that we
 have flattened C with O, and C with A. Product_Nested has two
 input streams, with CO in one and CA in the other. The branch type is C.
 For this discussion, let's assume that CO is the outer stream, and CA is in the
 input stream.

 For each CO row from the outer stream, a set of matching CA rows,
 (i.e., matching in C)
 from the input stream are retrieved. The CO row and all of the
 CA rows will have the same customer primary key. Product_Nested
 will write to the output stream product rows for each CO/CA
 combination.

 <h1>Output</h1>

 For CO/CA input streams, the format of an output row is (C, O, A),
 i.e., all the customer fields, followed by all the order fields,
 followed by all the address fields.

 Product rows do not have an hkey.

 <h1>Assumptions</h1>

 None.

 <h1>Performance</h1>

 Product_Nested does no IO.

 */

class Product_Nested extends Operator
{
    // Object interface

    @Override
    public String toString()
    {
        return String.format("%s(%s x %s)", getClass().getSimpleName(), outerType, inputType);
    }

    @Override
    public CompoundExplainer getExplainer(ExplainContext context)
    {
        Attributes atts = new Attributes();
        
        atts.put(Label.NAME, PrimitiveExplainer.getInstance(getName()));
        atts.put(Label.OUTER_TYPE, outerType.getExplainer(context));
        atts.put(Label.INNER_TYPE, inputType.getExplainer(context));
        atts.put(Label.INPUT_OPERATOR, inputOperator.getExplainer(context));
        atts.put(Label.BINDING_POSITION, PrimitiveExplainer.getInstance(bindingPosition));
        return new CompoundExplainer(Type.PRODUCT_OPERATOR, atts);
    }
    
    // Operator interface

    @Override
    protected Cursor cursor(QueryContext context, QueryBindingsCursor bindingsCursor)
    {
        return new Execution(context, inputOperator.cursor(context, bindingsCursor));
    }

    @Override
    public ProductRowType rowType()
    {
        return productType;
    }

    @Override
    public void findDerivedTypes(Set<RowType> derivedTypes)
    {
        inputOperator.findDerivedTypes(derivedTypes);
        derivedTypes.add(productType);
    }

    @Override
    public List<Operator> getInputOperators()
    {
        List<Operator> result = new ArrayList<>(2);
        result.add(inputOperator);
        return result;
    }

    @Override
    public String describePlan()
    {
        return describePlan(inputOperator);
    }

    // Product_Nested interface

    public Product_Nested(Operator inputOperator,
                          RowType outerType,
                          UserTableRowType branchType,
                          RowType inputType,
                          int bindingPosition)
    {
        ArgumentValidation.notNull("inputOperator", inputOperator);
        ArgumentValidation.notNull("outerType", outerType);
        ArgumentValidation.notNull("inputType", inputType);
        ArgumentValidation.isGTE("bindingPosition", bindingPosition, 0);
        this.inputOperator = inputOperator;
        this.outerType = outerType;
        this.inputType = inputType;
        this.productType = inputType.schema().newProductType(outerType, branchType, inputType);
        this.branchType = productType.branchType();
        this.bindingPosition = bindingPosition;
    }

    // Class state

    private static InOutTap TAP_OPEN = OPERATOR_TAP.createSubsidiaryTap("operator: Product_Nested open");
    private static InOutTap TAP_NEXT = OPERATOR_TAP.createSubsidiaryTap("operator: Product_Nested next");
    private static final Logger LOG = LoggerFactory.getLogger(Product_Nested.class);

    // Object state

    private final Operator inputOperator;
    private final RowType branchType;
    private final RowType outerType;
    private final RowType inputType;
    private final ProductRowType productType;
    private final int bindingPosition;

    // Inner classes

    private class Execution extends ChainedCursor
    {
        // Cursor interface

        @Override
        public Row next()
        {
            if (TAP_NEXT_ENABLED) {
                TAP_NEXT.in();
            }
            try {
                if (CURSOR_LIFECYCLE_ENABLED) {
                    CursorLifecycle.checkIdleOrActive(this);
                }
                checkQueryCancelation();
                Row row = input.next();
                if ((row != null) && (row.rowType() == inputType)) {
                    row = new ProductRow(productType, bindings.getRow(bindingPosition), row);
                }
                if (LOG_EXECUTION) {
                    LOG.debug("Product_Nested: yield {}", row);
                }
                return row;
            } finally {
                if (TAP_NEXT_ENABLED) {
                    TAP_NEXT.out();
                }
            }
        }

        // Execution interface

        Execution(QueryContext context, Cursor input)
        {
            super(context, input);
        }
    }
}

{'fraction_non_alphanumeric': 0.08443109685345711, 'fraction_numerical': 0.0072350010238209, 'mean_word_length': 2.7368018362662587, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3868611', 'n_tokens_mistral': 4221, 'n_tokens_neox': 3972, 'n_words': 1339}