private LanguageNode handleInFunction(FunctionCall fc) { ExpressionNode lhs = fc.getParameters().get(0); if (EngineConstant.COLUMN.has(lhs) && parent.isQualifyingColumn((ColumnInstance) lhs)) { // only matches if all the rhs are constant for (ExpressionNode en : fc.getParameters(1)) { if (!EngineConstant.CONSTANT.has(en)) return fc; } ColumnInstance ci = (ColumnInstance) lhs; if (!parent.isQualifyingColumn(ci.getPEColumn())) return fc; ArrayList<ExpressionNode> subexprs = new ArrayList<ExpressionNode>(); ArrayList<Part> parts = new ArrayList<Part>(); for (ExpressionNode en : fc.getParameters(1)) { ColumnInstance tci = (ColumnInstance) ci.copy(null); ConstantExpression litex = (ConstantExpression) en; ExpressionNode subeq = new FunctionCall(FunctionName.makeEquals(), tci, litex); Part p = buildPart(subeq, tci, litex); parts.add(p); subexprs.add((ExpressionNode) p.getParent()); } if (subexprs.size() > 1) { FunctionCall orcall = new FunctionCall(FunctionName.makeOr(), subexprs); OredParts pc = parent.buildOredParts(orcall, parts); if (pc.isComplete()) setComplete(pc); orcall.setGrouped(); state.put(orcall, pc); return orcall; } else { Part p = parts.get(0); return p.getParent(); } } return fc; }
private EqualityPart makeNewEqualityPart( EqualityPart existing, PEColumn c, ConstantExpression litex) { TableKey tk = existing.getColumn().getColumnKey().getTableKey(); ColumnInstance nc = new ColumnInstance(c, tk.toInstance()); FunctionCall eq = new FunctionCall(FunctionName.makeEquals(), nc, litex); EqualityPart eqp = buildEqualityPart(eq, nc, litex); return eqp; }
public static RedistFeatureStep buildLookupJoinRedist( PlannerContext pc, RedistFeatureStep lookupTable, List<ExpressionNode> lookupJoinColumns, PEStorageGroup targetGroup, JoinEntry origEntry, List<ExpressionNode> origJoinColumns, PartitionEntry nonLookupSide) throws PEException { // we will modify the existing non lookup side projecting feature step, and add the lookup table // as a requirement to it. ProjectingFeatureStep nonLookupStep = (ProjectingFeatureStep) nonLookupSide.getStep(null); nonLookupSide.maybeForceDoublePrecision(nonLookupStep); SelectStatement lookupSelect = lookupTable.getTargetTempTable().buildSelect(pc.getContext()); SelectStatement nonLookupSelect = (SelectStatement) nonLookupStep.getPlannedStatement(); SelectStatement actualJoinStatement = DMLStatementUtils.compose(pc.getContext(), nonLookupSelect, lookupSelect); List<ExpressionNode> ands = ExpressionUtils.decomposeAndClause(actualJoinStatement.getWhereClause()); // instead of building the join spec directly, map forward the original join condition from the // joined table if it's available IndexCollector ic = new IndexCollector(); if (origEntry.getJoin().getJoin() != null) { FunctionCall mapped = (FunctionCall) actualJoinStatement .getMapper() .copyForward(origEntry.getJoin().getJoin().getJoinOn()); ands.add(mapped); ListSet<ColumnInstance> cols = ColumnInstanceCollector.getColumnInstances(mapped); for (ColumnInstance ci : cols) ic.addColumnInstance(ci); } else { Map<RewriteKey, ExpressionNode> projEntries = null; for (int i = 0; i < origJoinColumns.size(); i++) { ColumnKey mck = actualJoinStatement.getMapper().mapExpressionToColumn(origJoinColumns.get(i)); ColumnKey muck = actualJoinStatement.getMapper().mapExpressionToColumn(lookupJoinColumns.get(i)); ExpressionNode mc = null; ExpressionNode muc = null; if (mck == null || muck == null) { if (projEntries == null) { projEntries = new HashMap<RewriteKey, ExpressionNode>(); for (ExpressionNode en : actualJoinStatement.getProjectionEdge()) { ExpressionNode actual = ExpressionUtils.getTarget(en); if (actual instanceof ColumnInstance) { projEntries.put(((ColumnInstance) actual).getColumnKey(), actual); } else { projEntries.put(new ExpressionKey(actual), actual); } } } if (mck == null) mc = (ExpressionNode) projEntries.get(new ExpressionKey(origJoinColumns.get(i))).copy(null); if (muck == null) mc = (ExpressionNode) projEntries.get(new ExpressionKey(lookupJoinColumns.get(i))).copy(null); } if (mc == null) mc = mck.toInstance(); if (muc == null) muc = muck.toInstance(); if (mc instanceof ColumnInstance) ic.addColumnInstance((ColumnInstance) mc); if (muc instanceof ColumnInstance) ic.addColumnInstance((ColumnInstance) muc); FunctionCall eq = new FunctionCall(FunctionName.makeEquals(), mc, muc); ands.add(eq); } } ic.setIndexes(origEntry.getSchemaContext()); TempTable lookupEntryTarget = lookupTable.getTargetTempTable(); // everything from the lhs that's in the projection should be cleared - it's invisible // note that we do it after building the where clause so that the original join condition can be // mapped for (Iterator<ExpressionNode> iter = actualJoinStatement.getProjectionEdge().iterator(); iter.hasNext(); ) { ExpressionNode en = iter.next(); ExpressionNode targ = ExpressionUtils.getTarget(en); if (targ instanceof ColumnInstance) { ColumnInstance ci = (ColumnInstance) targ; if (ci.getTableInstance().getAbstractTable() == lookupEntryTarget) iter.remove(); } } actualJoinStatement.setWhereClause(ExpressionUtils.safeBuildAnd(ands)); actualJoinStatement.normalize(origEntry.getSchemaContext()); // build a new projecting feature step ProjectingFeatureStep lookupJoinStep = DefaultFeatureStepBuilder.INSTANCE.buildProjectingStep( origEntry.getPlannerContext(), origEntry.getFeaturePlanner(), actualJoinStatement, new ExecutionCost(false, false, null, -1), nonLookupStep.getSourceGroup(), actualJoinStatement.getDatabase(origEntry.getSchemaContext()), nonLookupStep.getDistributionVector(), null, DMLExplainReason.LOOKUP_JOIN.makeRecord()); // arrange for the children of the nonlookup side to become my children // and add the lookup table step as well lookupJoinStep.getSelfChildren().addAll(nonLookupStep.getAllChildren()); lookupJoinStep.getSelfChildren().add(lookupTable); // children must be sequential - no need to modify here List<Integer> mappedRedistOn = nonLookupSide.mapDistributedOn(origJoinColumns, actualJoinStatement); // now remove the lookup table from the mapper - have to do this pretty late - at this point // the query won't be manipulated any more actualJoinStatement.getMapper().remove(lookupEntryTarget); RedistFeatureStep out = lookupJoinStep.redist( origEntry.getPlannerContext(), origEntry.getFeaturePlanner(), new TempTableCreateOptions(Model.STATIC, targetGroup) .distributeOn(mappedRedistOn) .withRowCount(origEntry.getScore().getRowCount()), null, DMLExplainReason.LOOKUP_JOIN.makeRecord()); return out; }