{"record":{"id":"7f493727224d0622","repo":"prestodb/presto","slug":"not-supported-7f4937","errorCode":"NOT_SUPPORTED","errorMessage":"unsupported function: %s","messagePattern":"unsupported function: (.+?)","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-iceberg/src/main/java/com/facebook/presto/iceberg/optimizer/IcebergMetadataOptimizer.java","lineNumber":352,"sourceCode":"            Type returnType = typeManager.getType(aggregationFunctionMetadata.getReturnType());\n            if (arguments.isEmpty()) {\n                return new ConstantExpression(Optional.empty(), null, returnType);\n            }\n\n            String scalarFunctionName = AGGREGATION_SCALAR_MAPPING.get(aggregationFunctionMetadata.getName().getObjectName());\n            while (arguments.size() > 1) {\n                List<RowExpression> reducedArguments = new ArrayList<>();\n                // We fold for every 100 values because GREATEST/LEAST has argument count limit\n                for (List<RowExpression> partitionedArguments : Lists.partition(arguments, 100)) {\n                    FunctionHandle functionHandle;\n                    if (scalarFunctionName.equals(\"greatest\")) {\n                        functionHandle = functionResolution.greatestFunction(partitionedArguments.stream().map(RowExpression::getType).collect(toImmutableList()));\n                    }\n                    else if (scalarFunctionName.equals(\"least\")) {\n                        functionHandle = functionResolution.leastFunction(partitionedArguments.stream().map(RowExpression::getType).collect(toImmutableList()));\n                    }\n                    else {\n                        throw new PrestoException(StandardErrorCode.NOT_SUPPORTED, \"unsupported function: \" + scalarFunctionName);\n                    }\n\n                    RowExpression reducedValue = rowExpressionService.getExpressionOptimizer(connectorSession).optimize(\n                            new CallExpression(\n                                    Optional.empty(),\n                                    scalarFunctionName,\n                                    functionHandle,\n                                    returnType,\n                                    partitionedArguments),\n                            Level.EVALUATED,\n                            connectorSession,\n                            variableReferenceExpression -> null);\n                    checkArgument(reducedValue instanceof ConstantExpression, \"unexpected expression type: %s\", reducedValue.getClass().getSimpleName());\n                    reducedArguments.add(reducedValue);\n                }\n                arguments = reducedArguments;\n            }\n            return getOnlyElement(arguments);","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-iceberg/src/main/java/com/facebook/presto/iceberg/optimizer/IcebergMetadataOptimizer.java#L334-L370","documentation":"IcebergMetadataOptimizer evaluates min/max expressions over partition values and only understands the scalar functions 'greatest' and 'least'. If a CallExpression in the filter predicate uses any other scalar function, evaluateMinMax throws NOT_SUPPORTED, because the optimizer cannot fold that expression into a partition-pruning range.","triggerScenarios":"Querying an Iceberg table whose partition filters contain scalar functions other than greatest/least over partition columns — e.g. WHERE year(partition_col) = 2024 or concat(a,b) = 'x' — when the optimizer tries to evaluate the min/max bound expression.","commonSituations":"Users writing function-wrapped predicates on partition columns expecting partition pruning; queries auto-generated by BI tools that wrap partition columns; newer custom functions reaching this optimizer path.","solutions":["Rewrite the predicate to compare the partition column directly, e.g. WHERE partition_col BETWEEN '2024-01-01' AND '2024-12-31' instead of wrapping it in a function.","Restructure filters so only greatest/least appear over partition values in prunable predicates.","If the function is essential, disable the optimizer path or file a feature request to support it.","Check EXPLAIN to confirm the rewritten predicate yields partition pruning."],"exampleFix":"// before\nSELECT * FROM t WHERE year(event_date) = 2024\n// after\nSELECT * FROM t WHERE event_date BETWEEN DATE '2024-01-01' AND DATE '2024-12-31'","handlingStrategy":"validation","validationCode":"-- keep partition-column predicates function-free for pruning\nSELECT * FROM t WHERE event_date BETWEEN DATE '2024-01-01' AND DATE '2024-12-31';","typeGuard":null,"tryCatchPattern":"try {\n  runQuery(predicate);\n} catch (PrestoException e) {\n  if (e.getErrorCode().getName().equals(\"NOT_SUPPORTED\")) {\n    // fall back to an unpruned query or rewrite predicate with only greatest/least\n  }\n}","preventionTips":["Never wrap partition columns in functions inside filter predicates.","Use range/comparison predicates directly on partition columns.","Check EXPLAIN for pruning after rewriting filters.","Restrict BI-tool auto-generated filters on partition columns."],"tags":[],"backgroundTag":null,"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"}