use of org.apache.calcite.rel.core.TableScan in project samza by apache.
the class JoinTranslator method isValidRemoteJoinRef.
/**
* Helper method to check if the join condition can be evaluated by the remote table.
* It does follow single path using the index ref path checking if it is a simple reference all the way to table scan.
* In case any RexCall is encountered will stop an return null as a marker otherwise will return Column Name.
*
* @param inputRexIndex rex ref index
* @param relNode current Rel Node
* @return false if any Relational Expression is encountered on the path, true if is simple ref to __key__ column.
*/
private static boolean isValidRemoteJoinRef(int inputRexIndex, RelNode relNode) {
if (relNode instanceof TableScan) {
return relNode.getRowType().getFieldList().get(inputRexIndex).getName().equals(SamzaSqlRelMessage.KEY_NAME);
}
// has to be a single rel kind filter/project/table scan
Preconditions.checkState(relNode.getInputs().size() == 1, "Has to be single input RelNode and got " + relNode.getDigest());
if (relNode instanceof LogicalFilter) {
return isValidRemoteJoinRef(inputRexIndex, relNode.getInput(0));
}
RexNode inputRef = ((LogicalProject) relNode).getProjects().get(inputRexIndex);
if (inputRef instanceof RexCall) {
// we can not push any expression as of now stop and return null.
return false;
}
return isValidRemoteJoinRef(((RexInputRef) inputRef).getIndex(), relNode.getInput(0));
}
use of org.apache.calcite.rel.core.TableScan in project samza by apache.
the class JoinTranslator method resolveSQlIOForTable.
static SqlIOConfig resolveSQlIOForTable(RelNode relNode, Map<String, SqlIOConfig> systemStreamConfigBySource) {
if (relNode instanceof HepRelVertex) {
return resolveSQlIOForTable(((HepRelVertex) relNode).getCurrentRel(), systemStreamConfigBySource);
}
if (relNode instanceof LogicalProject) {
return resolveSQlIOForTable(((LogicalProject) relNode).getInput(), systemStreamConfigBySource);
}
if (relNode instanceof LogicalFilter) {
return resolveSQlIOForTable(((LogicalFilter) relNode).getInput(), systemStreamConfigBySource);
}
// is considered a stream. Hence, we return null for the table.
if (relNode instanceof LogicalJoin && relNode.getInputs().size() > 1) {
return null;
}
if (!(relNode instanceof TableScan)) {
throw new SamzaException(String.format("Unsupported query. relNode %s is not of type TableScan.", relNode.toString()));
}
String sourceName = SqlIOConfig.getSourceFromSourceParts(relNode.getTable().getQualifiedName());
SqlIOConfig sourceConfig = systemStreamConfigBySource.get(sourceName);
if (sourceConfig == null) {
throw new SamzaException("Unsupported source found in join statement: " + sourceName);
}
return sourceConfig;
}
use of org.apache.calcite.rel.core.TableScan in project samza by apache.
the class QueryTranslator method translate.
/**
* Translate Calcite plan to Samza stream operators.
* @param relRoot Calcite plan in the form of {@link RelRoot}. RelRoot should not include the sink ({@link TableModify})
* @param outputSystemStream Sink associated with the Calcite plan.
* @param translatorContext Context maintained across translations.
* @param queryId query index of the sql statement corresponding to the Calcite plan in multi SQL statement scenario
* starting with index 0.
*/
public void translate(RelRoot relRoot, String outputSystemStream, TranslatorContext translatorContext, int queryId) {
final RelNode node = relRoot.project();
ScanTranslator scanTranslator = new ScanTranslator(sqlConfig.getSamzaRelConverters(), sqlConfig.getInputSystemStreamConfigBySource(), queryId);
/* update input metrics */
String queryLogicalId = String.format(TranslatorConstants.LOGSQLID_TEMPLATE, queryId);
opId = 0;
node.accept(new RelShuttleImpl() {
@Override
public RelNode visit(RelNode relNode) {
// There should never be a TableModify in the calcite plan.
Validate.isTrue(!(relNode instanceof TableModify));
return super.visit(relNode);
}
@Override
public RelNode visit(TableScan scan) {
RelNode node = super.visit(scan);
String logicalOpId = String.format(TranslatorConstants.LOGOPID_TEMPLATE, queryId, "scan", opId++);
scanTranslator.translate(scan, queryLogicalId, logicalOpId, translatorContext, systemDescriptors, inputMsgStreams);
return node;
}
@Override
public RelNode visit(LogicalFilter filter) {
RelNode node = visitChild(filter, 0, filter.getInput());
String logicalOpId = String.format(TranslatorConstants.LOGOPID_TEMPLATE, queryId, "filter", opId++);
new FilterTranslator(queryId).translate(filter, logicalOpId, translatorContext);
return node;
}
@Override
public RelNode visit(LogicalProject project) {
RelNode node = super.visit(project);
String logicalOpId = String.format(TranslatorConstants.LOGOPID_TEMPLATE, queryId, "project", opId++);
new ProjectTranslator(queryId).translate(project, logicalOpId, translatorContext);
return node;
}
@Override
public RelNode visit(LogicalJoin join) {
RelNode node = super.visit(join);
String logicalOpId = String.format(TranslatorConstants.LOGOPID_TEMPLATE, queryId, "join", opId++);
new JoinTranslator(logicalOpId, sqlConfig.getMetadataTopicPrefix(), queryId).translate(join, translatorContext);
return node;
}
@Override
public RelNode visit(LogicalAggregate aggregate) {
RelNode node = super.visit(aggregate);
String logicalOpId = String.format(TranslatorConstants.LOGOPID_TEMPLATE, queryId, "window", opId++);
new LogicalAggregateTranslator(logicalOpId, sqlConfig.getMetadataTopicPrefix()).translate(aggregate, translatorContext);
return node;
}
});
String logicalOpId = String.format(TranslatorConstants.LOGOPID_TEMPLATE, queryId, "insert", opId);
sendToOutputStream(queryLogicalId, logicalOpId, outputSystemStream, streamAppDescriptor, translatorContext, node, queryId);
}
use of org.apache.calcite.rel.core.TableScan in project calcite by apache.
the class CalcitePrepareImpl method analyze_.
private AnalyzeViewResult analyze_(SqlValidator validator, String sql, SqlNode sqlNode, RelRoot root, boolean fail) {
final RexBuilder rexBuilder = root.rel.getCluster().getRexBuilder();
RelNode rel = root.rel;
final RelNode viewRel = rel;
Project project;
if (rel instanceof Project) {
project = (Project) rel;
rel = project.getInput();
} else {
project = null;
}
Filter filter;
if (rel instanceof Filter) {
filter = (Filter) rel;
rel = filter.getInput();
} else {
filter = null;
}
TableScan scan;
if (rel instanceof TableScan) {
scan = (TableScan) rel;
} else {
scan = null;
}
if (scan == null) {
if (fail) {
throw validator.newValidationError(sqlNode, RESOURCE.modifiableViewMustBeBasedOnSingleTable());
}
return new AnalyzeViewResult(this, validator, sql, sqlNode, validator.getValidatedNodeType(sqlNode), root, null, null, null, null, false);
}
final RelOptTable targetRelTable = scan.getTable();
final RelDataType targetRowType = targetRelTable.getRowType();
final Table table = targetRelTable.unwrap(Table.class);
final List<String> tablePath = targetRelTable.getQualifiedName();
assert table != null;
List<Integer> columnMapping;
final Map<Integer, RexNode> projectMap = new HashMap<>();
if (project == null) {
columnMapping = ImmutableIntList.range(0, targetRowType.getFieldCount());
} else {
columnMapping = new ArrayList<>();
for (Ord<RexNode> node : Ord.zip(project.getProjects())) {
if (node.e instanceof RexInputRef) {
RexInputRef rexInputRef = (RexInputRef) node.e;
int index = rexInputRef.getIndex();
if (projectMap.get(index) != null) {
if (fail) {
throw validator.newValidationError(sqlNode, RESOURCE.moreThanOneMappedColumn(targetRowType.getFieldList().get(index).getName(), Util.last(tablePath)));
}
return new AnalyzeViewResult(this, validator, sql, sqlNode, validator.getValidatedNodeType(sqlNode), root, null, null, null, null, false);
}
projectMap.put(index, rexBuilder.makeInputRef(viewRel, node.i));
columnMapping.add(index);
} else {
columnMapping.add(-1);
}
}
}
final RexNode constraint;
if (filter != null) {
constraint = filter.getCondition();
} else {
constraint = rexBuilder.makeLiteral(true);
}
final List<RexNode> filters = new ArrayList<>();
// If we put a constraint in projectMap above, then filters will not be empty despite
// being a modifiable view.
final List<RexNode> filters2 = new ArrayList<>();
boolean retry = false;
RelOptUtil.inferViewPredicates(projectMap, filters, constraint);
if (fail && !filters.isEmpty()) {
final Map<Integer, RexNode> projectMap2 = new HashMap<>();
RelOptUtil.inferViewPredicates(projectMap2, filters2, constraint);
if (!filters2.isEmpty()) {
throw validator.newValidationError(sqlNode, RESOURCE.modifiableViewMustHaveOnlyEqualityPredicates());
}
retry = true;
}
// Check that all columns that are not projected have a constant value
for (RelDataTypeField field : targetRowType.getFieldList()) {
final int x = columnMapping.indexOf(field.getIndex());
if (x >= 0) {
assert Util.skip(columnMapping, x + 1).indexOf(field.getIndex()) < 0 : "column projected more than once; should have checked above";
// target column is projected
continue;
}
if (projectMap.get(field.getIndex()) != null) {
// constant expression
continue;
}
if (field.getType().isNullable()) {
// don't need expression for nullable columns; NULL suffices
continue;
}
if (fail) {
throw validator.newValidationError(sqlNode, RESOURCE.noValueSuppliedForViewColumn(field.getName(), Util.last(tablePath)));
}
return new AnalyzeViewResult(this, validator, sql, sqlNode, validator.getValidatedNodeType(sqlNode), root, null, null, null, null, false);
}
final boolean modifiable = filters.isEmpty() || retry && filters2.isEmpty();
return new AnalyzeViewResult(this, validator, sql, sqlNode, validator.getValidatedNodeType(sqlNode), root, modifiable ? table : null, ImmutableList.copyOf(tablePath), constraint, ImmutableIntList.copyOf(columnMapping), modifiable);
}
use of org.apache.calcite.rel.core.TableScan in project calcite by apache.
the class Prepare method optimize.
/**
* Optimizes a query plan.
*
* @param root Root of relational expression tree
* @param materializations Tables known to be populated with a given query
* @param lattices Lattices
* @return an equivalent optimized relational expression
*/
protected RelRoot optimize(RelRoot root, final List<Materialization> materializations, final List<CalciteSchema.LatticeEntry> lattices) {
final RelOptPlanner planner = root.rel.getCluster().getPlanner();
final DataContext dataContext = context.getDataContext();
planner.setExecutor(new RexExecutorImpl(dataContext));
final List<RelOptMaterialization> materializationList = new ArrayList<>();
for (Materialization materialization : materializations) {
List<String> qualifiedTableName = materialization.materializedTable.path();
materializationList.add(new RelOptMaterialization(materialization.tableRel, materialization.queryRel, materialization.starRelOptTable, qualifiedTableName));
}
final List<RelOptLattice> latticeList = new ArrayList<>();
for (CalciteSchema.LatticeEntry lattice : lattices) {
final CalciteSchema.TableEntry starTable = lattice.getStarTable();
final JavaTypeFactory typeFactory = context.getTypeFactory();
final RelOptTableImpl starRelOptTable = RelOptTableImpl.create(catalogReader, starTable.getTable().getRowType(typeFactory), starTable, null);
latticeList.add(new RelOptLattice(lattice.getLattice(), starRelOptTable));
}
final RelTraitSet desiredTraits = getDesiredRootTraitSet(root);
// Work around
// [CALCITE-1774] Allow rules to be registered during planning process
// by briefly creating each kind of physical table to let it register its
// rules. The problem occurs when plans are created via RelBuilder, not
// the usual process (SQL and SqlToRelConverter.Config.isConvertTableAccess
// = true).
final RelVisitor visitor = new RelVisitor() {
@Override
public void visit(RelNode node, int ordinal, RelNode parent) {
if (node instanceof TableScan) {
final RelOptCluster cluster = node.getCluster();
final RelOptTable.ToRelContext context = RelOptUtil.getContext(cluster);
final RelNode r = node.getTable().toRel(context);
planner.registerClass(r);
}
super.visit(node, ordinal, parent);
}
};
visitor.go(root.rel);
final Program program = getProgram();
final RelNode rootRel4 = program.run(planner, root.rel, desiredTraits, materializationList, latticeList);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Plan after physical tweaks: {}", RelOptUtil.toString(rootRel4, SqlExplainLevel.ALL_ATTRIBUTES));
}
return root.withRel(rootRel4);
}
Aggregations