{"record":{"id":"a75dae9e51e01d91","repo":"prestodb/presto","slug":"non-numeric-sample-percentage","errorCode":"NON_NUMERIC_SAMPLE_PERCENTAGE","errorMessage":"Sample percentage cannot contain column references","messagePattern":"Sample percentage cannot contain column references","errorType":"error_code","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java","lineNumber":3172,"sourceCode":"                    .map(Field::getName)\n                    .filter(Optional::isPresent)\n                    .map(Optional::get)\n                    // field names are resolved case-insensitive\n                    .map(name -> name.toLowerCase(ENGLISH))\n                    .forEach(name -> {\n                        if (!names.add(name)) {\n                            throw new SemanticException(DUPLICATE_COLUMN_NAME, relation.getRelation(), \"Duplicate name of table function proper column: \" + name);\n                        }\n                    });\n\n            return new RelationType(fields);\n        }\n\n        @Override\n        protected Scope visitSampledRelation(SampledRelation relation, Optional<Scope> scope)\n        {\n            if (!VariablesExtractor.extractNames(relation.getSamplePercentage(), analysis.getColumnReferences()).isEmpty()) {\n                throw new SemanticException(NON_NUMERIC_SAMPLE_PERCENTAGE, relation.getSamplePercentage(), \"Sample percentage cannot contain column references\");\n            }\n\n            Map<NodeRef<Expression>, Type> expressionTypes = getExpressionTypes(\n                    session,\n                    metadata,\n                    sqlParser,\n                    TypeProvider.empty(),\n                    relation.getSamplePercentage(),\n                    analysis.getParameters(),\n                    warningCollector,\n                    analysis.isDescribe());\n            ExpressionInterpreter samplePercentageEval = expressionOptimizer(relation.getSamplePercentage(), metadata, session, expressionTypes);\n\n            Object samplePercentageObject = samplePercentageEval.optimize(symbol -> {\n                throw new SemanticException(NON_NUMERIC_SAMPLE_PERCENTAGE, relation.getSamplePercentage(), \"Sample percentage cannot contain column references\");\n            });\n            try {\n                samplePercentageObject = evaluateConstantExpression(relation.getSamplePercentage(), DOUBLE, metadata, session,","sourceCodeStart":3154,"sourceCodeEnd":3190,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java#L3154-L3190","documentation":"TABLESAMPLE's sample percentage must be a constant expression; Presto extracts column references from the sample percentage expression and throws NON_NUMERIC_SAMPLE_PERCENTAGE if any are found. Allowing column references would make the sample ratio row-dependent, which the sampling implementation does not support.","triggerScenarios":"SELECT * FROM t TABLESAMPLE BERNOULLI (pct) where pct is a column of t; referencing any column (even from another table) inside the sample percentage expression.","commonSituations":"Trying to parameterize sample rate per row; storing sample sizes in a config table and referencing it in the query; misunderstanding that the percentage must be a literal/constant.","solutions":["Use a literal numeric percentage, e.g. TABLESAMPLE BERNOULLI (10)","Inline the desired value as a constant before running the query","Use a session-level parameter substituted at query construction time","If row-dependent sampling is needed, implement it with rand() <= ratio in a WHERE clause instead"],"exampleFix":"-- before\nSELECT * FROM t TABLESAMPLE BERNOULLI (pct)\n-- after\nSELECT * FROM t TABLESAMPLE BERNOULLI (10)","handlingStrategy":"validation","validationCode":"// sample percentage must be column-free before sending SQL\nSet<NodeRef<Expression>> cols = VariablesExtractor.extractNames(samplePctExpr, analysisRefs);\nif (!cols.isEmpty()) throw new IllegalArgumentException(\"sample percentage must be constant\");","typeGuard":"boolean isLiteralPercentage(Expression e) {\n    return e instanceof DoubleLiteral || e instanceof LongLiteral || e instanceof DecimalLiteral;\n}","tryCatchPattern":"try {\n    return engine.execute(sql);\n} catch (SemanticException e) {\n    if (e.getCode() == SemanticErrorCode.NON_NUMERIC_SAMPLE_PERCENTAGE) {\n        sql = replaceSamplePctWithLiteral(sql, fixedPct); // retry with constant\n    } else { throw e; }\n}","preventionTips":["Always use numeric literals for TABLESAMPLE percentages","Do not reference columns (even from other tables) in the sample percentage","For per-row sampling, use WHERE rand() <= ratio instead of TABLESAMPLE","Validate generated SQL templates to ensure sample rate substitution is constant"],"tags":["presto","sql","tablesample","constant-expression"],"backgroundTag":"non-constant-sample-percentage","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"}