/** Wraps a relational expression in the projects and filters implied by
* a {@link ModifiableView}.
*
* <p>The input relational expression is suitable for inserting into the view,
* and the returned relational expression is suitable for inserting into its
* delegate table.
*
* <p>In principle, the delegate table of a view might be another modifiable
* view, and if so, the process can be repeated. */
private RelNode createSource(RelOptTable targetTable, RelNode source,
ModifiableView modifiableView, RelDataType delegateRowType) {
final ImmutableIntList mapping = modifiableView.getColumnMapping();
assert mapping.size() == targetTable.getRowType().getFieldCount();
// For columns represented in the mapping, the expression is just a field
// reference.
final Map<Integer, RexNode> projectMap = new HashMap<>();
final List<RexNode> filters = new ArrayList<>();
for (int i = 0; i < mapping.size(); i++) {
int target = mapping.get(i);
if (target >= 0) {
projectMap.put(target, RexInputRef.of(i, source.getRowType()));
}
}
// For columns that are not in the mapping, and have a constraint of the
// form "column = value", the expression is the literal "value".
//
// If a column has multiple constraints, the extra ones will become a
// filter.
final RexNode constraint =
modifiableView.getConstraint(rexBuilder, delegateRowType);
RelOptUtil.inferViewPredicates(projectMap, filters, constraint);
final List<Pair<RexNode, String>> projects = new ArrayList<>();
for (RelDataTypeField field : delegateRowType.getFieldList()) {
RexNode node = projectMap.get(field.getIndex());
if (node == null) {
node = rexBuilder.makeNullLiteral(field.getType());
}
projects.add(
Pair.of(rexBuilder.ensureType(field.getType(), node, false),
field.getName()));
}
return relBuilder.push(source)
.projectNamed(Pair.left(projects), Pair.right(projects), false)
.filter(filters)
.build();
}
ModifiableView
A modifiable view onto ModifiableTable
.
It describes how its columns map onto the underlying table's columns, and any constraints that incoming rows must satisfy.
For example, given
CREATE TABLE emps (empno INTEGER, gender VARCHAR(1), deptno INTEGER); CREATE VIEW female_emps AS SELECT empno, deptno FROM emps WHERE gender = 'F';
constraint is $1 = 'F'
and column mapping is [0, 2]
.
NOTE: The current API is inefficient and experimental. It will change without notice.
insert female_emps (empno,gender
) values(1,'F')
insert emps (empno,gender
) values(SELECT (empno,gender
) FROM (empno,gender
) values(1,'F') WHERE gender = 'F');
支持的场景比较简单