Search in sources :

Example 1 with SqlColumnDeclaration

use of org.apache.calcite.sql.ddl.SqlColumnDeclaration in project ignite-3 by apache.

the class DdlSqlToCommandConverter method convertAlterTableAdd.

/**
 * Converts a given IgniteSqlAlterTableAddColumn AST to a AlterTableAddCommand.
 *
 * @param alterTblNode Root node of the given AST.
 * @param ctx          Planning context.
 */
private AlterTableAddCommand convertAlterTableAdd(IgniteSqlAlterTableAddColumn alterTblNode, PlanningContext ctx) {
    AlterTableAddCommand alterTblCmd = new AlterTableAddCommand();
    alterTblCmd.schemaName(deriveSchemaName(alterTblNode.name(), ctx));
    alterTblCmd.tableName(deriveObjectName(alterTblNode.name(), ctx, "table name"));
    alterTblCmd.ifTableExists(alterTblNode.ifExists());
    alterTblCmd.ifColumnNotExists(alterTblNode.ifNotExistsColumn());
    List<ColumnDefinition> cols = new ArrayList<>(alterTblNode.columns().size());
    for (SqlNode colNode : alterTblNode.columns()) {
        assert colNode instanceof SqlColumnDeclaration : colNode.getClass();
        SqlColumnDeclaration col = (SqlColumnDeclaration) colNode;
        assert col.name.isSimple();
        Object dflt = null;
        if (col.expression != null) {
            dflt = ((SqlLiteral) col.expression).getValue();
        }
        String name = col.name.getSimple();
        RelDataType relType = ctx.planner().convert(col.dataType, true);
        cols.add(new ColumnDefinition(name, relType, dflt));
    }
    alterTblCmd.columns(cols);
    return alterTblCmd;
}
Also used : ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlColumnDeclaration(org.apache.calcite.sql.ddl.SqlColumnDeclaration) SqlNode(org.apache.calcite.sql.SqlNode)

Example 2 with SqlColumnDeclaration

use of org.apache.calcite.sql.ddl.SqlColumnDeclaration in project dingo by dingodb.

the class DingoDdlExecutor method execute.

@SuppressWarnings({ "unused", "MethodMayBeStatic" })
public void execute(SqlCreateTable create, CalcitePrepare.Context context) {
    log.info("DDL execute: {}", create);
    final String tableName = getTableName(create.name, context);
    TableDefinition td = new TableDefinition(tableName);
    List<String> keyList = null;
    SqlNodeList columnList = create.columnList;
    if (columnList == null) {
        throw SqlUtil.newContextException(create.name.getParserPosition(), RESOURCE.createTableRequiresColumnList());
    }
    for (SqlNode sqlNode : create.columnList) {
        if (sqlNode instanceof SqlKeyConstraint) {
            SqlKeyConstraint constraint = (SqlKeyConstraint) sqlNode;
            if (constraint.getOperator().getKind() == SqlKind.PRIMARY_KEY) {
                // The 0th element is the name of the constraint
                keyList = ((SqlNodeList) constraint.getOperandList().get(1)).getList().stream().map(t -> ((SqlIdentifier) Objects.requireNonNull(t)).getSimple()).collect(Collectors.toList());
                break;
            }
        }
    }
    SqlValidator validator = new ContextSqlValidator(context, true);
    for (SqlNode sqlNode : create.columnList) {
        if (sqlNode.getKind() == SqlKind.COLUMN_DECL) {
            SqlColumnDeclaration scd = (SqlColumnDeclaration) sqlNode;
            ColumnDefinition cd = fromSqlColumnDeclaration(scd, validator, keyList);
            td.addColumn(cd);
        }
    }
    if (td.getColumns().stream().noneMatch(ColumnDefinition::isPrimary)) {
        throw new RuntimeException("Not have primary key!");
    }
    final MutableSchema schema = getSchema(context);
    if (schema.getTable(tableName) != null) {
        if (!create.ifNotExists) {
            // They did not specify IF NOT EXISTS, so give error.
            throw SqlUtil.newContextException(create.name.getParserPosition(), RESOURCE.tableExists(tableName));
        }
    }
    schema.createTable(tableName, td);
}
Also used : SqlValidator(org.apache.calcite.sql.validate.SqlValidator) ContextSqlValidator(org.apache.calcite.jdbc.ContextSqlValidator) TableDefinition(io.dingodb.common.table.TableDefinition) SqlNodeList(org.apache.calcite.sql.SqlNodeList) ContextSqlValidator(org.apache.calcite.jdbc.ContextSqlValidator) SqlColumnDeclaration(org.apache.calcite.sql.ddl.SqlColumnDeclaration) SqlKeyConstraint(org.apache.calcite.sql.ddl.SqlKeyConstraint) SqlNode(org.apache.calcite.sql.SqlNode) ColumnDefinition(io.dingodb.common.table.ColumnDefinition)

Example 3 with SqlColumnDeclaration

use of org.apache.calcite.sql.ddl.SqlColumnDeclaration in project calcite by apache.

the class ServerDdlExecutor method execute.

/**
 * Executes a {@code CREATE TABLE} command.
 */
public void execute(SqlCreateTable create, CalcitePrepare.Context context) {
    final Pair<CalciteSchema, String> pair = schema(context, true, create.name);
    final JavaTypeFactory typeFactory = context.getTypeFactory();
    final RelDataType queryRowType;
    if (create.query != null) {
        // A bit of a hack: pretend it's a view, to get its row type
        final String sql = create.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 (create.columnList != null && queryRowType.getFieldCount() != create.columnList.size()) {
            throw SqlUtil.newContextException(create.columnList.getParserPosition(), RESOURCE.columnCountMismatch());
        }
    } else {
        queryRowType = null;
    }
    final List<SqlNode> columnList;
    if (create.columnList != null) {
        columnList = create.columnList;
    } else {
        if (queryRowType == null) {
            // a list of column names and types, "CREATE TABLE t (INT c)".
            throw SqlUtil.newContextException(create.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();
    // REVIEW 2019-08-19 Danny Chan: Should we implement the
    // #validate(SqlValidator) to get the SqlValidator instance?
    final SqlValidator validator = validator(context, true);
    for (Ord<SqlNode> c : Ord.zip(columnList)) {
        if (c.e instanceof SqlColumnDeclaration) {
            final SqlColumnDeclaration d = (SqlColumnDeclaration) c.e;
            final RelDataType type = d.dataType.deriveType(validator, 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) {
                // REVIEW Danny 2019-10-09: Should we support validation for DDL nodes?
                final SqlNode validated = context.validateExpression(storedRowType, c.expr);
                // actually they should be exactly the same.
                return context.convertExpression(validated);
            }
            return super.newColumnDefaultValue(table, iColumn, context);
        }
    };
    if (pair.left.plus().getTable(pair.right) != null) {
        // Table exists.
        if (create.ifNotExists) {
            return;
        }
        if (!create.getReplace()) {
            // They did not specify IF NOT EXISTS, so give error.
            throw SqlUtil.newContextException(create.name.getParserPosition(), RESOURCE.tableExists(pair.right));
        }
    }
    // Table does not exist. Create it.
    pair.left.add(pair.right, new MutableArrayTable(pair.right, RelDataTypeImpl.proto(storedRowType), RelDataTypeImpl.proto(rowType), ief));
    if (create.query != null) {
        populate(create.name, create.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) NlsString(org.apache.calcite.util.NlsString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlColumnDeclaration(org.apache.calcite.sql.ddl.SqlColumnDeclaration) SqlValidator(org.apache.calcite.sql.validate.SqlValidator) ContextSqlValidator(org.apache.calcite.jdbc.ContextSqlValidator) 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 4 with SqlColumnDeclaration

use of org.apache.calcite.sql.ddl.SqlColumnDeclaration in project ignite-3 by apache.

the class DdlSqlToCommandConverter method convertCreateTable.

/**
 * Converts a given CreateTable AST to a CreateTable command.
 *
 * @param createTblNode Root node of the given AST.
 * @param ctx           Planning context.
 */
private CreateTableCommand convertCreateTable(IgniteSqlCreateTable createTblNode, PlanningContext ctx) {
    CreateTableCommand createTblCmd = new CreateTableCommand();
    createTblCmd.schemaName(deriveSchemaName(createTblNode.name(), ctx));
    createTblCmd.tableName(deriveObjectName(createTblNode.name(), ctx, "tableName"));
    createTblCmd.ifTableExists(createTblNode.ifNotExists());
    if (createTblNode.createOptionList() != null) {
        for (SqlNode optNode : createTblNode.createOptionList().getList()) {
            IgniteSqlCreateTableOption opt = (IgniteSqlCreateTableOption) optNode;
            tblOptionProcessors.getOrDefault(opt.key(), UNSUPPORTED_OPTION_PROCESSOR).process(opt, ctx, createTblCmd);
        }
    }
    List<SqlKeyConstraint> pkConstraints = createTblNode.columnList().getList().stream().filter(SqlKeyConstraint.class::isInstance).map(SqlKeyConstraint.class::cast).collect(Collectors.toList());
    if (nullOrEmpty(pkConstraints)) {
        throw new IgniteException("Table without PRIMARY KEY is not supported");
    } else if (pkConstraints.size() > 1) {
        throw new IgniteException("Unexpected amount of primary key constraints [" + "expected at most one, but was " + pkConstraints.size() + "; " + "querySql=\"" + ctx.query() + "\"]");
    }
    Set<String> dedupSetPk = new HashSet<>();
    List<String> pkCols = pkConstraints.stream().map(pk -> pk.getOperandList().get(1)).map(SqlNodeList.class::cast).flatMap(l -> l.getList().stream()).map(SqlIdentifier.class::cast).map(SqlIdentifier::getSimple).filter(dedupSetPk::add).collect(Collectors.toList());
    createTblCmd.primaryKeyColumns(pkCols);
    List<SqlColumnDeclaration> colDeclarations = createTblNode.columnList().getList().stream().filter(SqlColumnDeclaration.class::isInstance).map(SqlColumnDeclaration.class::cast).collect(Collectors.toList());
    IgnitePlanner planner = ctx.planner();
    List<ColumnDefinition> cols = new ArrayList<>(colDeclarations.size());
    for (SqlColumnDeclaration col : colDeclarations) {
        if (!col.name.isSimple()) {
            throw new IgniteException("Unexpected value of columnName [" + "expected a simple identifier, but was " + col.name + "; " + "querySql=\"" + ctx.query() + "\"]");
        }
        String name = col.name.getSimple();
        if (col.dataType.getNullable() != null && col.dataType.getNullable() && dedupSetPk.contains(name)) {
            throw new IgniteException("Primary key cannot contain nullable column [col=" + name + "]");
        }
        RelDataType relType = planner.convert(col.dataType, !dedupSetPk.contains(name));
        dedupSetPk.remove(name);
        Object dflt = null;
        if (col.expression != null) {
            dflt = ((SqlLiteral) col.expression).getValue();
        }
        cols.add(new ColumnDefinition(name, relType, dflt));
    }
    if (!dedupSetPk.isEmpty()) {
        throw new IgniteException("Primary key constrain contains undefined columns: [cols=" + dedupSetPk + "]");
    }
    createTblCmd.columns(cols);
    return createTblCmd;
}
Also used : IgniteSqlCreateTableOption(org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateTableOption) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlColumnDeclaration(org.apache.calcite.sql.ddl.SqlColumnDeclaration) SqlKeyConstraint(org.apache.calcite.sql.ddl.SqlKeyConstraint) IgnitePlanner(org.apache.ignite.internal.sql.engine.prepare.IgnitePlanner) IgniteException(org.apache.ignite.lang.IgniteException) SqlNode(org.apache.calcite.sql.SqlNode) HashSet(java.util.HashSet)

Aggregations

SqlNode (org.apache.calcite.sql.SqlNode)4 SqlColumnDeclaration (org.apache.calcite.sql.ddl.SqlColumnDeclaration)4 RelDataType (org.apache.calcite.rel.type.RelDataType)3 ArrayList (java.util.ArrayList)2 ContextSqlValidator (org.apache.calcite.jdbc.ContextSqlValidator)2 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)2 SqlKeyConstraint (org.apache.calcite.sql.ddl.SqlKeyConstraint)2 SqlValidator (org.apache.calcite.sql.validate.SqlValidator)2 ImmutableList (com.google.common.collect.ImmutableList)1 ColumnDefinition (io.dingodb.common.table.ColumnDefinition)1 TableDefinition (io.dingodb.common.table.TableDefinition)1 HashSet (java.util.HashSet)1 JavaTypeFactory (org.apache.calcite.adapter.java.JavaTypeFactory)1 CalciteSchema (org.apache.calcite.jdbc.CalciteSchema)1 RelOptTable (org.apache.calcite.plan.RelOptTable)1 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)1 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)1 ColumnStrategy (org.apache.calcite.schema.ColumnStrategy)1 TranslatableTable (org.apache.calcite.schema.TranslatableTable)1 ViewTableMacro (org.apache.calcite.schema.impl.ViewTableMacro)1