Search in sources :

Example 1 with ColumnStrategy

use of org.apache.calcite.schema.ColumnStrategy in project calcite by apache.

the class SqlToRelConverter method createInsertBlackboard.

/**
 * Creates a blackboard for translating the expressions of generated columns
 * in an INSERT statement.
 */
private Blackboard createInsertBlackboard(RelOptTable targetTable, RexNode sourceRef, List<String> targetColumnNames) {
    final Map<String, RexNode> nameToNodeMap = new HashMap<>();
    int j = 0;
    // Assign expressions for non-generated columns.
    final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
    final List<String> targetFields = targetTable.getRowType().getFieldNames();
    for (String targetColumnName : targetColumnNames) {
        final int i = targetFields.indexOf(targetColumnName);
        switch(strategies.get(i)) {
            case STORED:
            case VIRTUAL:
                break;
            default:
                nameToNodeMap.put(targetColumnName, rexBuilder.makeFieldAccess(sourceRef, j++));
        }
    }
    return createBlackboard(null, nameToNodeMap, false);
}
Also used : ColumnStrategy(org.apache.calcite.schema.ColumnStrategy) HashMap(java.util.HashMap) NlsString(org.apache.calcite.util.NlsString) RexNode(org.apache.calcite.rex.RexNode)

Example 2 with ColumnStrategy

use of org.apache.calcite.schema.ColumnStrategy in project calcite by apache.

the class SqlToRelConverter method toRel.

public RelNode toRel(final RelOptTable table) {
    final RelNode scan = table.toRel(createToRelContext());
    final InitializerExpressionFactory ief = Util.first(table.unwrap(InitializerExpressionFactory.class), NullInitializerExpressionFactory.INSTANCE);
    // Lazily create a blackboard that contains all non-generated columns.
    final Supplier<Blackboard> bb = new Supplier<Blackboard>() {

        public Blackboard get() {
            RexNode sourceRef = rexBuilder.makeRangeReference(scan);
            return createInsertBlackboard(table, sourceRef, table.getRowType().getFieldNames());
        }
    };
    int virtualCount = 0;
    final List<RexNode> list = new ArrayList<>();
    for (RelDataTypeField f : table.getRowType().getFieldList()) {
        final ColumnStrategy strategy = ief.generationStrategy(table, f.getIndex());
        switch(strategy) {
            case VIRTUAL:
                list.add(ief.newColumnDefaultValue(table, f.getIndex(), bb.get()));
                ++virtualCount;
                break;
            default:
                list.add(rexBuilder.makeInputRef(scan, RelOptTableImpl.realOrdinal(table, f.getIndex())));
        }
    }
    if (virtualCount > 0) {
        relBuilder.push(scan);
        relBuilder.project(list);
        return relBuilder.build();
    }
    return scan;
}
Also used : ColumnStrategy(org.apache.calcite.schema.ColumnStrategy) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) ArrayList(java.util.ArrayList) Supplier(com.google.common.base.Supplier) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with ColumnStrategy

use of org.apache.calcite.schema.ColumnStrategy in project calcite by apache.

the class SqlToRelConverter method collectInsertTargets.

/**
 * Given an INSERT statement, collects the list of names to be populated and
 * the expressions to put in them.
 *
 * @param call              Insert statement
 * @param sourceRef         Expression representing a row from the source
 *                          relational expression
 * @param targetColumnNames List of target column names, to be populated
 * @param columnExprs       List of expressions, to be populated
 */
protected void collectInsertTargets(SqlInsert call, final RexNode sourceRef, final List<String> targetColumnNames, List<RexNode> columnExprs) {
    final RelOptTable targetTable = getTargetTable(call);
    final RelDataType tableRowType = targetTable.getRowType();
    SqlNodeList targetColumnList = call.getTargetColumnList();
    if (targetColumnList == null) {
        if (validator.getConformance().isInsertSubsetColumnsAllowed()) {
            final RelDataType targetRowType = typeFactory.createStructType(tableRowType.getFieldList().subList(0, sourceRef.getType().getFieldCount()));
            targetColumnNames.addAll(targetRowType.getFieldNames());
        } else {
            targetColumnNames.addAll(tableRowType.getFieldNames());
        }
    } else {
        for (int i = 0; i < targetColumnList.size(); i++) {
            SqlIdentifier id = (SqlIdentifier) targetColumnList.get(i);
            RelDataTypeField field = SqlValidatorUtil.getTargetField(tableRowType, typeFactory, id, catalogReader, targetTable);
            assert field != null : "column " + id.toString() + " not found";
            targetColumnNames.add(field.getName());
        }
    }
    final Blackboard bb = createInsertBlackboard(targetTable, sourceRef, targetColumnNames);
    // Next, assign expressions for generated columns.
    final List<ColumnStrategy> strategies = targetTable.getColumnStrategies();
    for (String columnName : targetColumnNames) {
        final int i = tableRowType.getFieldNames().indexOf(columnName);
        final RexNode expr;
        switch(strategies.get(i)) {
            case STORED:
                final InitializerExpressionFactory f = Util.first(targetTable.unwrap(InitializerExpressionFactory.class), NullInitializerExpressionFactory.INSTANCE);
                expr = f.newColumnDefaultValue(targetTable, i, bb);
                break;
            case VIRTUAL:
                expr = null;
                break;
            default:
                expr = bb.nameToNodeMap.get(columnName);
        }
        columnExprs.add(expr);
    }
    // Remove virtual columns from the list.
    for (int i = 0; i < targetColumnNames.size(); i++) {
        if (columnExprs.get(i) == null) {
            columnExprs.remove(i);
            targetColumnNames.remove(i);
            --i;
        }
    }
}
Also used : ColumnStrategy(org.apache.calcite.schema.ColumnStrategy) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) SqlNodeList(org.apache.calcite.sql.SqlNodeList) RelDataType(org.apache.calcite.rel.type.RelDataType) RelOptTable(org.apache.calcite.plan.RelOptTable) NlsString(org.apache.calcite.util.NlsString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) RexNode(org.apache.calcite.rex.RexNode)

Example 4 with ColumnStrategy

use of org.apache.calcite.schema.ColumnStrategy in project calcite by apache.

the class SqlCreateTable method execute.

public void execute(CalcitePrepare.Context context) {
    final Pair<CalciteSchema, String> pair = SqlDdlNodes.schema(context, true, name);
    final JavaTypeFactory typeFactory = new JavaTypeFactoryImpl();
    final RelDataType queryRowType;
    if (query != null) {
        // A bit of a hack: pretend it's a view, to get its row type
        final String sql = query.toSqlString(CalciteSqlDialect.DEFAULT).getSql();
        final ViewTableMacro viewTableMacro = ViewTable.viewMacro(pair.left.plus(), sql, pair.left.path(null), context.getObjectPath(), false);
        final TranslatableTable x = viewTableMacro.apply(ImmutableList.of());
        queryRowType = x.getRowType(typeFactory);
        if (columnList != null && queryRowType.getFieldCount() != columnList.size()) {
            throw SqlUtil.newContextException(columnList.getParserPosition(), RESOURCE.columnCountMismatch());
        }
    } else {
        queryRowType = null;
    }
    final List<SqlNode> columnList;
    if (this.columnList != null) {
        columnList = this.columnList.getList();
    } else {
        if (queryRowType == null) {
            // a list of column names and types, "CREATE TABLE t (INT c)".
            throw SqlUtil.newContextException(name.getParserPosition(), RESOURCE.createTableRequiresColumnList());
        }
        columnList = new ArrayList<>();
        for (String name : queryRowType.getFieldNames()) {
            columnList.add(new SqlIdentifier(name, SqlParserPos.ZERO));
        }
    }
    final ImmutableList.Builder<ColumnDef> b = ImmutableList.builder();
    final RelDataTypeFactory.Builder builder = typeFactory.builder();
    final RelDataTypeFactory.Builder storedBuilder = typeFactory.builder();
    for (Ord<SqlNode> c : Ord.zip(columnList)) {
        if (c.e instanceof SqlColumnDeclaration) {
            final SqlColumnDeclaration d = (SqlColumnDeclaration) c.e;
            final RelDataType type = d.dataType.deriveType(typeFactory, true);
            builder.add(d.name.getSimple(), type);
            if (d.strategy != ColumnStrategy.VIRTUAL) {
                storedBuilder.add(d.name.getSimple(), type);
            }
            b.add(ColumnDef.of(d.expression, type, d.strategy));
        } else if (c.e instanceof SqlIdentifier) {
            final SqlIdentifier id = (SqlIdentifier) c.e;
            if (queryRowType == null) {
                throw SqlUtil.newContextException(id.getParserPosition(), RESOURCE.createTableRequiresColumnTypes(id.getSimple()));
            }
            final RelDataTypeField f = queryRowType.getFieldList().get(c.i);
            final ColumnStrategy strategy = f.getType().isNullable() ? ColumnStrategy.NULLABLE : ColumnStrategy.NOT_NULLABLE;
            b.add(ColumnDef.of(c.e, f.getType(), strategy));
            builder.add(id.getSimple(), f.getType());
            storedBuilder.add(id.getSimple(), f.getType());
        } else {
            throw new AssertionError(c.e.getClass());
        }
    }
    final RelDataType rowType = builder.build();
    final RelDataType storedRowType = storedBuilder.build();
    final List<ColumnDef> columns = b.build();
    final InitializerExpressionFactory ief = new NullInitializerExpressionFactory() {

        @Override
        public ColumnStrategy generationStrategy(RelOptTable table, int iColumn) {
            return columns.get(iColumn).strategy;
        }

        @Override
        public RexNode newColumnDefaultValue(RelOptTable table, int iColumn, InitializerContext context) {
            final ColumnDef c = columns.get(iColumn);
            if (c.expr != null) {
                return context.convertExpression(c.expr);
            }
            return super.newColumnDefaultValue(table, iColumn, context);
        }
    };
    if (pair.left.plus().getTable(pair.right) != null) {
        // Table exists.
        if (!ifNotExists) {
            // They did not specify IF NOT EXISTS, so give error.
            throw SqlUtil.newContextException(name.getParserPosition(), RESOURCE.tableExists(pair.right));
        }
        return;
    }
    // Table does not exist. Create it.
    pair.left.add(pair.right, new MutableArrayTable(pair.right, RelDataTypeImpl.proto(storedRowType), RelDataTypeImpl.proto(rowType), ief));
    if (query != null) {
        SqlDdlNodes.populate(name, query, context);
    }
}
Also used : NullInitializerExpressionFactory(org.apache.calcite.sql2rel.NullInitializerExpressionFactory) NullInitializerExpressionFactory(org.apache.calcite.sql2rel.NullInitializerExpressionFactory) InitializerExpressionFactory(org.apache.calcite.sql2rel.InitializerExpressionFactory) ImmutableList(com.google.common.collect.ImmutableList) ViewTableMacro(org.apache.calcite.schema.impl.ViewTableMacro) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) JavaTypeFactoryImpl(org.apache.calcite.jdbc.JavaTypeFactoryImpl) JavaTypeFactory(org.apache.calcite.adapter.java.JavaTypeFactory) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) TranslatableTable(org.apache.calcite.schema.TranslatableTable) SqlNode(org.apache.calcite.sql.SqlNode) ColumnStrategy(org.apache.calcite.schema.ColumnStrategy) InitializerContext(org.apache.calcite.sql2rel.InitializerContext) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) CalciteSchema(org.apache.calcite.jdbc.CalciteSchema) RelOptTable(org.apache.calcite.plan.RelOptTable)

Example 5 with ColumnStrategy

use of org.apache.calcite.schema.ColumnStrategy in project flink by apache.

the class SqlValidatorImpl method validateInsert.

public void validateInsert(SqlInsert insert) {
    final SqlValidatorNamespace targetNamespace = getNamespace(insert);
    validateNamespace(targetNamespace, unknownType);
    final RelOptTable relOptTable = SqlValidatorUtil.getRelOptTable(targetNamespace, catalogReader.unwrap(Prepare.CatalogReader.class), null, null);
    final SqlValidatorTable table = relOptTable == null ? targetNamespace.getTable() : relOptTable.unwrap(SqlValidatorTable.class);
    // INSERT has an optional column name list.  If present then
    // reduce the rowtype to the columns specified.  If not present
    // then the entire target rowtype is used.
    final RelDataType targetRowType = createTargetRowType(table, insert.getTargetColumnList(), false);
    final SqlNode source = insert.getSource();
    if (source instanceof SqlSelect) {
        final SqlSelect sqlSelect = (SqlSelect) source;
        validateSelect(sqlSelect, targetRowType);
    } else {
        final SqlValidatorScope scope = scopes.get(source);
        validateQuery(source, scope, targetRowType);
    }
    // REVIEW jvs 4-Dec-2008: In FRG-365, this namespace row type is
    // discarding the type inferred by inferUnknownTypes (which was invoked
    // from validateSelect above).  It would be better if that information
    // were used here so that we never saw any untyped nulls during
    // checkTypeAssignment.
    final RelDataType sourceRowType = getNamespace(source).getRowType();
    final RelDataType logicalTargetRowType = getLogicalTargetRowType(targetRowType, insert);
    setValidatedNodeType(insert, logicalTargetRowType);
    final RelDataType logicalSourceRowType = getLogicalSourceRowType(sourceRowType, insert);
    final List<ColumnStrategy> strategies = table.unwrap(RelOptTable.class).getColumnStrategies();
    final RelDataType realTargetRowType = typeFactory.createStructType(logicalTargetRowType.getFieldList().stream().filter(f -> strategies.get(f.getIndex()).canInsertInto()).collect(Collectors.toList()));
    final RelDataType targetRowTypeToValidate = logicalSourceRowType.getFieldCount() == logicalTargetRowType.getFieldCount() ? logicalTargetRowType : realTargetRowType;
    checkFieldCount(insert.getTargetTable(), table, strategies, targetRowTypeToValidate, realTargetRowType, source, logicalSourceRowType, logicalTargetRowType);
    checkTypeAssignment(scopes.get(source), table, logicalSourceRowType, targetRowTypeToValidate, insert);
    checkConstraint(table, source, logicalTargetRowType);
    validateAccess(insert.getTargetTable(), table, SqlAccessEnum.INSERT);
    // Refresh the insert row type to keep sync with source.
    setValidatedNodeType(insert, targetRowTypeToValidate);
}
Also used : ColumnStrategy(org.apache.calcite.schema.ColumnStrategy) SqlSelect(org.apache.calcite.sql.SqlSelect) RelDataType(org.apache.calcite.rel.type.RelDataType) RelOptTable(org.apache.calcite.plan.RelOptTable) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

ColumnStrategy (org.apache.calcite.schema.ColumnStrategy)9 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)6 RelOptTable (org.apache.calcite.plan.RelOptTable)5 RelDataType (org.apache.calcite.rel.type.RelDataType)5 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)3 RexNode (org.apache.calcite.rex.RexNode)3 SqlNode (org.apache.calcite.sql.SqlNode)3 TranslatableTable (org.apache.calcite.schema.TranslatableTable)2 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)2 InitializerContext (org.apache.calcite.sql2rel.InitializerContext)2 NlsString (org.apache.calcite.util.NlsString)2 Supplier (com.google.common.base.Supplier)1 ImmutableList (com.google.common.collect.ImmutableList)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 JavaTypeFactory (org.apache.calcite.adapter.java.JavaTypeFactory)1 CalciteSchema (org.apache.calcite.jdbc.CalciteSchema)1 JavaTypeFactoryImpl (org.apache.calcite.jdbc.JavaTypeFactoryImpl)1 RelOptCluster (org.apache.calcite.plan.RelOptCluster)1 RelNode (org.apache.calcite.rel.RelNode)1