{"record":{"id":"902c48696e44f2b1","repo":"bytebase/bytebase","slug":"failed-to-resolve-positional-column-reference-s","errorCode":null,"errorMessage":"failed to resolve positional column reference $%s","messagePattern":"failed to resolve positional column reference \\$(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/parser/snowflake/query_span_extractor.go","lineNumber":1403,"sourceCode":"// resolvePositionalRef resolves a positional column reference $N (optionally\n// qualified, d.$1) to the N-th column of the FROM scope (or of the qualified\n// relation), mirroring the legacy DOLLAR/Column_position branch: errors on a\n// non-numeric, < 1, or out-of-range position.\nfunc (q *querySpanExtractor) resolvePositionalRef(dollar *ast.DollarRef) (base.QuerySpanResult, error) {\n\tposition, err := strconv.Atoi(dollar.Name)\n\tif err != nil {\n\t\treturn base.QuerySpanResult{}, errors.Wrapf(err, \"failed to parse column position %q to integer\", dollar.Name)\n\t}\n\tif position < 1 {\n\t\treturn base.QuerySpanResult{}, errors.Errorf(\"column position %d is invalid because it is less than 1\", position)\n\t}\n\tvar normalizedDatabaseName, normalizedSchemaName, normalizedTableName string\n\tif dollar.Qualifier != nil {\n\t\tnormalizedDatabaseName, normalizedSchemaName, normalizedTableName = normalizeSnowflakeObjectName(dollar.Qualifier, \"\", \"\")\n\t}\n\tleft, err := q.getAllFieldsOfTableInFromOrOuterCTE(normalizedDatabaseName, normalizedSchemaName, normalizedTableName)\n\tif err != nil {\n\t\treturn base.QuerySpanResult{}, errors.Wrapf(err, \"failed to resolve positional column reference $%s\", dollar.Name)\n\t}\n\tif position > len(left) {\n\t\treturn base.QuerySpanResult{}, errors.Errorf(\"column position $%d is invalid: the FROM clause only returns %d columns\", position, len(left))\n\t}\n\treturn left[position-1], nil\n}\n\n// applyStarRenames applies the `SELECT * RENAME (col AS alias, ...)` transform\n// to a star expansion: the matching result columns keep their lineage but take\n// the alias as their output name (Snowflake returns the renamed column).\n// Matching uses normalized identifiers, like the rest of the resolver.\nfunc applyStarRenames(columns []base.QuerySpanResult, renames []ast.StarRename) []base.QuerySpanResult {\n\tif len(renames) == 0 {\n\t\treturn columns\n\t}\n\taliasByColumn := make(map[string]string, len(renames))\n\tfor _, r := range renames {\n\t\taliasByColumn[normalizeSnowflakeIdentifier(r.Col)] = normalizeSnowflakeIdentifier(r.Alias)","sourceCodeStart":1385,"sourceCodeEnd":1421,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/parser/snowflake/query_span_extractor.go#L1385-L1421","documentation":"Before indexing into the positional columns, resolvePositionalRef must fetch the fields of the qualified (or unqualified) FROM table or outer CTE. If that lookup fails — e.g. no matching table for the qualifier — the underlying error is wrapped with this message.","triggerScenarios":"A qualified positional reference like t.$1 where table t is not in the FROM clause or outer CTE scope, producing the inner 'no matching table' error.","commonSituations":"Qualifying $1 with an alias that does not exist; referencing an outer CTE that is not visible at this nesting level.","solutions":["Correct or drop the qualifier on the $n reference so it binds to an in-scope table","Ensure the referenced table/CTE alias matches exactly (case after normalization)","Inspect the wrapped cause ('no matching table ...') to identify which qualifier failed"],"exampleFix":"// before: SELECT o.$1 FROM orders -- alias 'o' undeclared\nSELECT orders.$1 FROM orders\n// after (or unqualified)\nSELECT $1 FROM orders","handlingStrategy":"try-catch","validationCode":"if qualifier != nil && !scopeHasTable(qualifier) {\n  return errors.New(\"positional ref qualifier not in FROM scope\")\n}","typeGuard":null,"tryCatchPattern":"res, err := extractor.ExtractQuerySpan(stmt)\nvar serr *SpanError\nif errors.As(err, &serr) && strings.Contains(err.Error(), \"failed to resolve positional column reference\") {\n  // fall back to unqualified $n or skip the column\n}","preventionTips":["Only qualify $n refs with aliases present in FROM","Prefer unqualified positional refs when a single table is in scope","Inspect wrapped 'no matching table' causes for the offending qualifier"],"tags":["snowflake","sql-analysis","positional-reference"],"backgroundTag":"record-not-found","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}