Search in sources :

Example 1 with RelColumnMapping

use of org.apache.calcite.rel.metadata.RelColumnMapping in project calcite by apache.

the class TableFunctionReturnTypeInference method addOutputColumn.

private void addOutputColumn(List<String> expandedFieldNames, List<RelDataType> expandedOutputTypes, int iInputColumn, int iCursor, SqlOperatorBinding opBinding, RelDataTypeField cursorField) {
    columnMappings.add(new RelColumnMapping(expandedFieldNames.size(), iCursor, iInputColumn, !isPassthrough));
    // As a special case, system fields are implicitly NOT NULL.
    // A badly behaved UDX can still provide NULL values, so the
    // system must ensure that each generated system field has a
    // reasonable value.
    boolean nullable = true;
    if (opBinding instanceof SqlCallBinding) {
        SqlCallBinding sqlCallBinding = (SqlCallBinding) opBinding;
        if (sqlCallBinding.getValidator().isSystemField(cursorField)) {
            nullable = false;
        }
    }
    RelDataType nullableType = opBinding.getTypeFactory().createTypeWithNullability(cursorField.getType(), nullable);
    // Make sure there are no duplicates in the output column names
    for (String fieldName : expandedFieldNames) {
        if (fieldName.equals(cursorField.getName())) {
            throw opBinding.newError(RESOURCE.duplicateColumnName(cursorField.getName()));
        }
    }
    expandedOutputTypes.add(nullableType);
    expandedFieldNames.add(cursorField.getName());
}
Also used : SqlCallBinding(org.apache.calcite.sql.SqlCallBinding) RelDataType(org.apache.calcite.rel.type.RelDataType) RelColumnMapping(org.apache.calcite.rel.metadata.RelColumnMapping)

Example 2 with RelColumnMapping

use of org.apache.calcite.rel.metadata.RelColumnMapping in project calcite by apache.

the class FilterTableFunctionTransposeRule method onMatch.

// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
    LogicalFilter filter = call.rel(0);
    LogicalTableFunctionScan funcRel = call.rel(1);
    Set<RelColumnMapping> columnMappings = funcRel.getColumnMappings();
    if (columnMappings == null || columnMappings.isEmpty()) {
        // possible.
        return;
    }
    List<RelNode> funcInputs = funcRel.getInputs();
    if (funcInputs.size() != 1) {
        // offsetting field indices, similar to join
        return;
    }
    // TODO:  support mappings other than 1-to-1
    if (funcRel.getRowType().getFieldCount() != funcInputs.get(0).getRowType().getFieldCount()) {
        return;
    }
    for (RelColumnMapping mapping : columnMappings) {
        if (mapping.iInputColumn != mapping.iOutputColumn) {
            return;
        }
        if (mapping.derived) {
            return;
        }
    }
    final List<RelNode> newFuncInputs = new ArrayList<RelNode>();
    final RelOptCluster cluster = funcRel.getCluster();
    final RexNode condition = filter.getCondition();
    // create filters on top of each func input, modifying the filter
    // condition to reference the child instead
    RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
    List<RelDataTypeField> origFields = funcRel.getRowType().getFieldList();
    // TODO:  these need to be non-zero once we
    // support arbitrary mappings
    int[] adjustments = new int[origFields.size()];
    for (RelNode funcInput : funcInputs) {
        RexNode newCondition = condition.accept(new RelOptUtil.RexInputConverter(rexBuilder, origFields, funcInput.getRowType().getFieldList(), adjustments));
        newFuncInputs.add(LogicalFilter.create(funcInput, newCondition));
    }
    // create a new UDX whose children are the filters created above
    LogicalTableFunctionScan newFuncRel = LogicalTableFunctionScan.create(cluster, newFuncInputs, funcRel.getCall(), funcRel.getElementType(), funcRel.getRowType(), columnMappings);
    call.transformTo(newFuncRel);
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) LogicalFilter(org.apache.calcite.rel.logical.LogicalFilter) RelOptUtil(org.apache.calcite.plan.RelOptUtil) ArrayList(java.util.ArrayList) LogicalTableFunctionScan(org.apache.calcite.rel.logical.LogicalTableFunctionScan) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexBuilder(org.apache.calcite.rex.RexBuilder) RelColumnMapping(org.apache.calcite.rel.metadata.RelColumnMapping) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with RelColumnMapping

use of org.apache.calcite.rel.metadata.RelColumnMapping in project calcite by apache.

the class TableFunctionReturnTypeInference method inferReturnType.

public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
    columnMappings = new HashSet<RelColumnMapping>();
    RelDataType unexpandedOutputType = protoType.apply(opBinding.getTypeFactory());
    List<RelDataType> expandedOutputTypes = new ArrayList<RelDataType>();
    List<String> expandedFieldNames = new ArrayList<String>();
    for (RelDataTypeField field : unexpandedOutputType.getFieldList()) {
        RelDataType fieldType = field.getType();
        String fieldName = field.getName();
        if (fieldType.getSqlTypeName() != SqlTypeName.CURSOR) {
            expandedOutputTypes.add(fieldType);
            expandedFieldNames.add(fieldName);
            continue;
        }
        // Look up position of cursor parameter with same name as output
        // field, also counting how many cursors appear before it
        // (need this for correspondence with RelNode child position).
        int paramOrdinal = -1;
        int iCursor = 0;
        for (int i = 0; i < paramNames.size(); ++i) {
            if (paramNames.get(i).equals(fieldName)) {
                paramOrdinal = i;
                break;
            }
            RelDataType cursorType = opBinding.getCursorOperand(i);
            if (cursorType != null) {
                ++iCursor;
            }
        }
        assert paramOrdinal != -1;
        // Translate to actual argument type.
        boolean isRowOp = false;
        List<String> columnNames = new ArrayList<String>();
        RelDataType cursorType = opBinding.getCursorOperand(paramOrdinal);
        if (cursorType == null) {
            isRowOp = true;
            String parentCursorName = opBinding.getColumnListParamInfo(paramOrdinal, fieldName, columnNames);
            assert parentCursorName != null;
            paramOrdinal = -1;
            iCursor = 0;
            for (int i = 0; i < paramNames.size(); ++i) {
                if (paramNames.get(i).equals(parentCursorName)) {
                    paramOrdinal = i;
                    break;
                }
                cursorType = opBinding.getCursorOperand(i);
                if (cursorType != null) {
                    ++iCursor;
                }
            }
            cursorType = opBinding.getCursorOperand(paramOrdinal);
            assert cursorType != null;
        }
        // And expand. Function output is always nullable... except system
        // fields.
        int iInputColumn;
        if (isRowOp) {
            for (String columnName : columnNames) {
                iInputColumn = -1;
                RelDataTypeField cursorField = null;
                for (RelDataTypeField cField : cursorType.getFieldList()) {
                    ++iInputColumn;
                    if (cField.getName().equals(columnName)) {
                        cursorField = cField;
                        break;
                    }
                }
                addOutputColumn(expandedFieldNames, expandedOutputTypes, iInputColumn, iCursor, opBinding, cursorField);
            }
        } else {
            iInputColumn = -1;
            for (RelDataTypeField cursorField : cursorType.getFieldList()) {
                ++iInputColumn;
                addOutputColumn(expandedFieldNames, expandedOutputTypes, iInputColumn, iCursor, opBinding, cursorField);
            }
        }
    }
    return opBinding.getTypeFactory().createStructType(expandedOutputTypes, expandedFieldNames);
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) RelColumnMapping(org.apache.calcite.rel.metadata.RelColumnMapping)

Example 4 with RelColumnMapping

use of org.apache.calcite.rel.metadata.RelColumnMapping in project calcite by apache.

the class SqlToRelConverter method convertCollectionTable.

protected void convertCollectionTable(Blackboard bb, SqlCall call) {
    final SqlOperator operator = call.getOperator();
    if (operator == SqlStdOperatorTable.TABLESAMPLE) {
        final String sampleName = SqlLiteral.unchain(call.operand(0)).getValueAs(String.class);
        datasetStack.push(sampleName);
        SqlCall cursorCall = call.operand(1);
        SqlNode query = cursorCall.operand(0);
        RelNode converted = convertQuery(query, false, false).rel;
        bb.setRoot(converted, false);
        datasetStack.pop();
        return;
    }
    replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
    // Expand table macro if possible. It's more efficient than
    // LogicalTableFunctionScan.
    final SqlCallBinding callBinding = new SqlCallBinding(bb.scope.getValidator(), bb.scope, call);
    if (operator instanceof SqlUserDefinedTableMacro) {
        final SqlUserDefinedTableMacro udf = (SqlUserDefinedTableMacro) operator;
        final TranslatableTable table = udf.getTable(typeFactory, callBinding.operands());
        final RelDataType rowType = table.getRowType(typeFactory);
        RelOptTable relOptTable = RelOptTableImpl.create(null, rowType, table, udf.getNameAsId().names);
        RelNode converted = toRel(relOptTable);
        bb.setRoot(converted, true);
        return;
    }
    Type elementType;
    if (operator instanceof SqlUserDefinedTableFunction) {
        SqlUserDefinedTableFunction udtf = (SqlUserDefinedTableFunction) operator;
        elementType = udtf.getElementType(typeFactory, callBinding.operands());
    } else {
        elementType = null;
    }
    RexNode rexCall = bb.convertExpression(call);
    final List<RelNode> inputs = bb.retrieveCursors();
    Set<RelColumnMapping> columnMappings = getColumnMappings(operator);
    LogicalTableFunctionScan callRel = LogicalTableFunctionScan.create(cluster, inputs, rexCall, elementType, validator.getValidatedNodeType(call), columnMappings);
    bb.setRoot(callRel, true);
    afterTableFunction(bb, call, callRel);
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) SqlCall(org.apache.calcite.sql.SqlCall) SqlUserDefinedTableMacro(org.apache.calcite.sql.validate.SqlUserDefinedTableMacro) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) LogicalTableFunctionScan(org.apache.calcite.rel.logical.LogicalTableFunctionScan) JoinType(org.apache.calcite.sql.JoinType) RelDataType(org.apache.calcite.rel.type.RelDataType) JoinRelType(org.apache.calcite.rel.core.JoinRelType) JoinConditionType(org.apache.calcite.sql.JoinConditionType) Type(java.lang.reflect.Type) SemiJoinType(org.apache.calcite.sql.SemiJoinType) SqlUserDefinedTableFunction(org.apache.calcite.sql.validate.SqlUserDefinedTableFunction) RelNode(org.apache.calcite.rel.RelNode) SqlCallBinding(org.apache.calcite.sql.SqlCallBinding) TranslatableTable(org.apache.calcite.schema.TranslatableTable) RelOptTable(org.apache.calcite.plan.RelOptTable) RelColumnMapping(org.apache.calcite.rel.metadata.RelColumnMapping) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RelColumnMapping (org.apache.calcite.rel.metadata.RelColumnMapping)4 RelDataType (org.apache.calcite.rel.type.RelDataType)3 ArrayList (java.util.ArrayList)2 RelNode (org.apache.calcite.rel.RelNode)2 LogicalTableFunctionScan (org.apache.calcite.rel.logical.LogicalTableFunctionScan)2 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)2 RexNode (org.apache.calcite.rex.RexNode)2 SqlCallBinding (org.apache.calcite.sql.SqlCallBinding)2 Type (java.lang.reflect.Type)1 RelOptCluster (org.apache.calcite.plan.RelOptCluster)1 RelOptTable (org.apache.calcite.plan.RelOptTable)1 RelOptUtil (org.apache.calcite.plan.RelOptUtil)1 JoinRelType (org.apache.calcite.rel.core.JoinRelType)1 LogicalFilter (org.apache.calcite.rel.logical.LogicalFilter)1 RexBuilder (org.apache.calcite.rex.RexBuilder)1 TranslatableTable (org.apache.calcite.schema.TranslatableTable)1 JoinConditionType (org.apache.calcite.sql.JoinConditionType)1 JoinType (org.apache.calcite.sql.JoinType)1 SemiJoinType (org.apache.calcite.sql.SemiJoinType)1 SqlCall (org.apache.calcite.sql.SqlCall)1