public static boolean isCountConstant(ProjectNode projectNode, FunctionCall functionCall, Signature signature) { if (!"count".equals(signature.getName()) || signature.getArgumentTypes().size() != 1 || !signature.getReturnType().getBase().equals(StandardTypes.BIGINT)) { return false; } Expression argument = functionCall.getArguments().get(0); if (argument instanceof Literal && !(argument instanceof NullLiteral)) { return true; } if (argument instanceof QualifiedNameReference) { QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) argument; QualifiedName qualifiedName = qualifiedNameReference.getName(); Symbol argumentSymbol = Symbol.fromQualifiedName(qualifiedName); Expression argumentExpression = projectNode.getAssignments().get(argumentSymbol); return (argumentExpression instanceof Literal) && (!(argumentExpression instanceof NullLiteral)); } return false; }
private boolean canConvertOuterToInner(List<Symbol> innerSymbolsForOuterJoin, Expression inheritedPredicate) { Set<Symbol> innerSymbols = ImmutableSet.copyOf(innerSymbolsForOuterJoin); for (Expression conjunct : extractConjuncts(inheritedPredicate)) { if (DeterminismEvaluator.isDeterministic(conjunct)) { // Ignore a conjunct for this test if we can not deterministically get responses from it Object response = nullInputEvaluator(innerSymbols, conjunct); if (response == null || response instanceof NullLiteral || Boolean.FALSE.equals(response)) { // If there is a single conjunct that returns FALSE or NULL given all NULL inputs for the inner side symbols of an outer join // then this conjunct removes all effects of the outer join, and effectively turns this into an equivalent of an inner join. // So, let's just rewrite this join as an INNER join return true; } } } return false; }
private boolean shouldPrune(Expression predicate, Map<Symbol, ColumnHandle> assignments, Map<ColumnHandle, NullableValue> bindings) { List<Expression> conjuncts = extractConjuncts(predicate); IdentityHashMap<Expression, Type> expressionTypes = getExpressionTypes(session, metadata, parser, symbolAllocator.getTypes(), predicate); LookupSymbolResolver inputs = new LookupSymbolResolver(assignments, bindings); // If any conjuncts evaluate to FALSE or null, then the whole predicate will never be true and so the partition should be pruned for (Expression expression : conjuncts) { ExpressionInterpreter optimizer = ExpressionInterpreter.expressionOptimizer(expression, metadata, session, expressionTypes); Object optimized = optimizer.optimize(inputs); if (Boolean.FALSE.equals(optimized) || optimized == null || optimized instanceof NullLiteral) { return true; } } return false; }
protected static String processFuncNullifzero(Formatter formatter, FunctionCall node) { Expression x = node.getArguments().get(0); List<WhenClause> listWhen = new ArrayList<WhenClause>(); ComparisonExpression ce = new ComparisonExpression(ComparisonExpression.Type.EQUAL, x, new LongLiteral("0")); WhenClause wc = new WhenClause(ce, new NullLiteral()); listWhen.add(wc); SearchedCaseExpression sce = new SearchedCaseExpression(listWhen, x); return formatter.process(sce, null); }
@Override public PlanNode visitFilter(FilterNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); Expression simplified = simplifyExpression(node.getPredicate()); if (simplified.equals(TRUE_LITERAL)) { return source; } // TODO: this needs to check whether the boolean expression coerces to false in a more general way. // E.g., simplify() not always produces a literal when the expression is constant else if (simplified.equals(FALSE_LITERAL) || simplified instanceof NullLiteral) { return new ValuesNode(idAllocator.getNextId(), node.getOutputSymbols(), ImmutableList.of()); } return new FilterNode(node.getId(), source, simplified); }
@Override public PlanNode visitMarkDistinct(MarkDistinctNode node, RewriteContext<Optional<Symbol>> context) { Optional<Symbol> mask = context.get(); if (mask.isPresent() && mask.get().equals(node.getMarkerSymbol())) { // rewrite Distinct into GroupBy AggregationNode aggregationNode = new AggregationNode(idAllocator.getNextId(), context.rewrite(node.getSource(), Optional.empty()), node.getDistinctSymbols(), Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), SINGLE, Optional.empty(), 1.0, node.getHashSymbol()); ImmutableMap.Builder<Symbol, Expression> outputSymbols = ImmutableMap.builder(); for (Symbol symbol : aggregationNode.getOutputSymbols()) { Expression expression = new QualifiedNameReference(symbol.toQualifiedName()); outputSymbols.put(symbol, expression); } // add null assignment for mask // unused mask will be removed by PruneUnreferencedOutputs outputSymbols.put(mask.get(), new NullLiteral()); return new ProjectNode(idAllocator.getNextId(), aggregationNode, outputSymbols.build()); } return context.defaultRewrite(node, Optional.empty()); }
@Override protected String visitNullLiteral(NullLiteral node, Void context) { return "null"; }
@Override protected String visitNullLiteral(NullLiteral node, StackableAstVisitorContext<Integer> indent) { return "null"; }
@Override protected RowExpression visitNullLiteral(NullLiteral node, Void context) { return constantNull(UnknownType.UNKNOWN); }
private RelationPlan createInsertPlan(Analysis analysis) { Analysis.Insert insert = analysis.getInsert().get(); TableMetadata tableMetadata = metadata.getTableMetadata(session, insert.getTarget()); List<String> visibleTableColumnNames = tableMetadata.getVisibleColumnNames(); List<ColumnMetadata> visibleTableColumns = tableMetadata.getVisibleColumns(); RelationPlan plan = createRelationPlan(analysis); Map<String, ColumnHandle> columns = metadata.getColumnHandles(session, insert.getTarget()); ImmutableMap.Builder<Symbol, Expression> assignments = ImmutableMap.builder(); for (ColumnMetadata column : tableMetadata.getVisibleColumns()) { Symbol output = symbolAllocator.newSymbol(column.getName(), column.getType()); int index = insert.getColumns().indexOf(columns.get(column.getName())); if (index < 0) { assignments.put(output, new NullLiteral()); } else { assignments.put(output, plan.getSymbol(index).toQualifiedNameReference()); } } ProjectNode projectNode = new ProjectNode(idAllocator.getNextId(), plan.getRoot(), assignments.build()); RelationType tupleDescriptor = new RelationType(visibleTableColumns.stream() .map(column -> Field.newUnqualified(column.getName(), column.getType())) .collect(toImmutableList())); plan = new RelationPlan( projectNode, tupleDescriptor, projectNode.getOutputSymbols(), plan.getSampleWeight()); return createTableWriterPlan( analysis, plan, new InsertReference(insert.getTarget()), visibleTableColumnNames); }
@Override protected Object visitNullLiteral(NullLiteral node, ConnectorSession session) { return null; }
@Override public PlanNode visitProject(ProjectNode node, RewriteContext<Void> context) { PlanNode source = context.rewrite(node.getSource()); Map<Expression, Symbol> computedExpressions = new HashMap<>(); Map<Symbol, Expression> assignments = new LinkedHashMap<>(); for (Map.Entry<Symbol, Expression> entry : node.getAssignments().entrySet()) { Expression expression = canonicalize(entry.getValue()); if (expression instanceof QualifiedNameReference) { // Always map a trivial symbol projection Symbol symbol = Symbol.fromQualifiedName(((QualifiedNameReference) expression).getName()); if (!symbol.equals(entry.getKey())) { map(entry.getKey(), symbol); } } else if (DeterminismEvaluator.isDeterministic(expression) && !(expression instanceof NullLiteral)) { // Try to map same deterministic expressions within a projection into the same symbol // Omit NullLiterals since those have ambiguous types Symbol computedSymbol = computedExpressions.get(expression); if (computedSymbol == null) { // If we haven't seen the expression before in this projection, record it computedExpressions.put(expression, entry.getKey()); } else { // If we have seen the expression before and if it is deterministic // then we can rewrite references to the current symbol in terms of the parallel computedSymbol in the projection map(entry.getKey(), computedSymbol); } } Symbol canonical = canonicalize(entry.getKey()); if (!assignments.containsKey(canonical)) { assignments.put(canonical, expression); } } return new ProjectNode(node.getId(), source, assignments); }
@Override protected ExtractionResult visitNullLiteral(NullLiteral node, Boolean complement) { return new ExtractionResult(TupleDomain.none(), TRUE_LITERAL); }
@Override protected Type visitNullLiteral(NullLiteral node, StackableAstVisitorContext<AnalysisContext> context) { expressionTypes.put(node, UNKNOWN); return UNKNOWN; }
private static NullLiteral nullLiteral() { return new NullLiteral(); }
@Override public Node visitNullLiteral(SqlBaseParser.NullLiteralContext context) { return new NullLiteral(getLocation(context)); }
@Override protected String visitNullLiteral(NullLiteral node, Boolean unmangleNames) { return "null"; }
private static void assertCast(String type, String expected) { assertExpression("CAST(null AS " + type + ")", new Cast(new NullLiteral(), expected)); }