prestodb/presto · error · SemanticException

TABLE_FUNCTION_INVALID_COLUMN_REFERENCE

TABLE_FUNCTION_INVALID_COLUMN_REFERENCE

Error message

Expected column reference. Actual: %s

What it means

A table function argument expected a column reference — an Identifier or DereferenceExpression such as t.col — but received some other expression. validateAndGetInputField in StatementAnalyzer only handles these two node types for resolving input columns and throws TABLE_FUNCTION_INVALID_COLUMN_REFERENCE otherwise.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java:2226

                                                        }
                                                    })))
                                            .collect(toImmutableList())))
                                    .build())
                            .orElse(NULL_DESCRIPTOR),
                    Optional.empty());
        }

        private Field validateAndGetInputField(Expression expression, Scope inputScope)
        {
            QualifiedName qualifiedName;
            if (expression instanceof Identifier) {
                qualifiedName = QualifiedName.of(ImmutableList.of(((Identifier) expression)));
            }
            else if (expression instanceof DereferenceExpression) {
                qualifiedName = getQualifiedName((DereferenceExpression) expression);
            }
            else {
                throw new SemanticException(TABLE_FUNCTION_INVALID_COLUMN_REFERENCE, expression, "Expected column reference. Actual: %s", expression);
            }
            Optional<ResolvedField> field = inputScope.tryResolveField(expression, qualifiedName);
            if (!field.isPresent() || !field.get().isLocal()) {
                throw new SemanticException(TABLE_FUNCTION_COLUMN_NOT_FOUND, expression, "Column %s is not present in the input relation", expression);
            }

            return field.get().getField();
        }

        private List<List<String>> analyzeCopartitioning(List<List<QualifiedName>> copartitioning, List<TableArgumentAnalysis> tableArgumentAnalyses)
        {
            // map table arguments by relation names. usa a multimap, because multiple arguments can have the same value, e.g. input_1 => tpch.tiny.orders, input_2 => tpch.tiny.orders
            ImmutableMultimap.Builder<QualifiedName, TableArgumentAnalysis> unqualifiedInputsBuilder = ImmutableMultimap.builder();
            ImmutableMultimap.Builder<QualifiedName, TableArgumentAnalysis> qualifiedInputsBuilder = ImmutableMultimap.builder();
            tableArgumentAnalyses.stream()
                    .filter(argument -> argument.getName().isPresent())
                    .forEach(argument -> {
                        QualifiedName name = argument.getName().get();

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Pass a bare column reference: identifier or table.column form.
  2. Compute derived values in a subquery/CTE first, then pass the projected column.
  3. Use DESCRIPTOR(...) if the parameter expects column descriptors, not expressions.

Example fix

// before
TABLE(fn(input => (SELECT a + 1 AS b FROM t), col => b + 1))

// after
WITH prepared AS (SELECT a + 1 AS b FROM t)
SELECT * FROM TABLE(fn(input => prepared, col => b))
Defensive patterns

Strategy: validation

Validate before calling

// Only pass plain column references (identifier or table.column) to table-function slots
Pattern COL_REF = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*");
if (!COL_REF.matcher(argExpr.trim()).matches()) {
    throw new IllegalArgumentException("Expected column reference, got expression: " + argExpr);
}

Type guard

boolean isColumnReference(String expr) {
    return expr != null && expr.trim().matches("[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*");
}

Prevention

When it happens

Trigger: Passing an arbitrary expression into a table argument's column-reference slot, e.g. PASSING t.a + 1 AS x, a function call, a CASE expression, or a literal where a plain column is required.

Common situations: Trying to compute derived columns inside table function arguments; wrapping column names in expressions or functions like lower(col).

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/252a2c77d2eec793. Report an issue: GitHub.