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);
}
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;
}
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;
}
}
}
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);
}
}
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);
}
Aggregations