{"record":{"id":"120209457ddde7ea","repo":"prestodb/presto","slug":"not-supported-120209","errorCode":"NOT_SUPPORTED","errorMessage":"Unsupported function for materialized view rewrite: %s","messagePattern":"Unsupported function for materialized view rewrite: (.+?)","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/MaterializedViewExpressionRewriter.java","lineNumber":108,"sourceCode":"    {\n        Map<Expression, Identifier> columnMap = mvInfo.getBaseToViewColumnMap();\n        if (!columnMap.containsKey(node)) {\n            throw new IllegalStateException(\"Materialized view definition does not contain mapping for the column: \" + node.getValue());\n        }\n        return new Identifier(columnMap.get(node).getValue(), node.isDelimited());\n    }\n\n    public Expression rewriteFunctionCall(FunctionCall node, Function<Expression, Expression> argRewriter)\n    {\n        Map<Expression, Identifier> baseToViewColumnMap = mvInfo.getBaseToViewColumnMap();\n\n        if (NON_ASSOCIATIVE_REWRITE_FUNCTIONS.containsKey(node.getName())) {\n            return MaterializedViewUtils.rewriteNonAssociativeFunction(node, baseToViewColumnMap);\n        }\n\n        if (!ASSOCIATIVE_REWRITE_FUNCTIONS.contains(node.getName())) {\n            if (!isScalarFunction(node)) {\n                throw new SemanticException(NOT_SUPPORTED, node, \"Unsupported function for materialized view rewrite: \" + node.getName());\n            }\n            return rebuildWithRewrittenArgs(node, argRewriter);\n        }\n\n        if (baseToViewColumnMap.containsKey(node)) {\n            return rewriteAssociativeFunction(node, baseToViewColumnMap.get(node));\n        }\n\n        if (mvInfo.getGroupBy().isPresent()) {\n            throw new SemanticException(NOT_SUPPORTED, node, \"Materialized view does not pre-compute aggregate: \" + node.getName());\n        }\n\n        return rebuildWithRewrittenArgs(node, argRewriter);\n    }\n\n    public boolean isScalarFunction(FunctionCall functionCall)\n    {\n        return !functionCall.getWindow().isPresent()","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/MaterializedViewExpressionRewriter.java#L90-L126","documentation":"During materialized-view-based query rewrite, Presto rewrites aggregate functions over base tables into references to pre-computed columns in the materialized view. Only a fixed whitelist of associative functions (and designated non-associative rewrite functions) is supported. When a function call is neither whitelisted nor a scalar function, the rewriter cannot safely map it onto the view, so it throws NOT_SUPPORTED.","triggerScenarios":"Querying a base table with an aggregate expression (e.g. AVG, MEDIAN, or any custom aggregate function) whose materialized view definition contains the same function but it is not in ASSOCIATIVE_REWRITE_FUNCTIONS or NON_ASSOCIATIVE_REWRITE_FUNCTIONS, and it is not a scalar function; rewriteFunctionCall is invoked from the MV rewrite visitor during planning.","commonSituations":"Users create a materialized view computing a non-whitelisted aggregate (e.g. AVG(x), STDDEV, custom UDA) and then query the base table expecting automatic rewrite; adding new SQL functions without extending the whitelist; connector/plugin functions that are aggregates but not registered as rewriteable.","solutions":["Rewrite the query or materialized view to use supported associative functions (SUM, COUNT, MIN, MAX, etc.) and derive other aggregates from them (e.g. AVG = SUM/COUNT).","Add the function to ASSOCIATIVE_REWRITE_FUNCTIONS (or NON_ASSOCIATIVE_REWRITE_FUNCTIONS with a corresponding rewrite rule in MaterializedViewUtils.rewriteNonAssociativeFunction) if it can be safely rewritten.","Query the materialized view directly instead of the base table so the rewrite pass is not needed.","Disable materialized view rewrite routing for that query/session."],"exampleFix":"// before (query)\nSELECT dept, AVG(salary) FROM employee GROUP BY dept; -- MV holds AVG(salary)\n// after\nSELECT dept, SUM(salary)/SUM(salary_count) AS avg_salary FROM employee GROUP BY dept; -- MV stores SUM(salary) and COUNT(salary)","handlingStrategy":"try-catch","validationCode":"// Before relying on MV rewrite, ensure the view only uses supported aggregates:\n// Supported: SUM, COUNT, MIN, MAX (associative whitelist) plus AVG etc. via\n// MaterializedViewUtils.rewriteNonAssociativeFunction. Check ASSOCIATIVE_REWRITE_FUNCTIONS /\n// NON_ASSOCIATIVE_REWRITE_FUNCTIONS in MaterializedViewExpressionRewriter before creating the MV.","typeGuard":null,"tryCatchPattern":"try {\n    planner.execute(query);\n} catch (SemanticException e) {\n    if (e.getCode() == SemanticErrorCode.NOT_SUPPORTED && e.getMessage().contains(\"Unsupported function for materialized view rewrite\")) {\n        // fall back to base-table query without MV rewrite\n    } else { throw e; }\n}","preventionTips":["Only use whitelisted associative aggregates in MV definitions.","Derive AVG/variance-style aggregates from SUM/COUNT columns stored in the view.","Test MV-backed queries in CI to catch rewrite failures early.","Keep function whitelist changes documented for view authors."],"tags":["materialized-view","not-supported","planner","presto"],"backgroundTag":"materialized-view-rewrite-unsupported-function","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}