{"record":{"id":"c582057b8d1b4aa4","repo":"bytebase/bytebase","slug":"column-alias-count-d-does-not-match-column-count","errorCode":null,"errorMessage":"column alias count %d does not match column count %d","messagePattern":"column alias count (.+?) does not match column count (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/parser/tsql/query_span_extractor_omni.go","lineNumber":906,"sourceCode":"\t\tName:    sel.IntoTable.Object,\n\t\tColumns: columns,\n\t}\n}\n\nfunc xmlNodesColumns(cols []string) []base.QuerySpanResult {\n\tout := make([]base.QuerySpanResult, 0, len(cols))\n\tfor _, c := range cols {\n\t\tout = append(out, base.QuerySpanResult{Name: c})\n\t}\n\treturn out\n}\n\nfunc applyColumnAliases(cols []base.QuerySpanResult, aliases []string) error {\n\tif len(aliases) == 0 {\n\t\treturn nil\n\t}\n\tif len(aliases) != len(cols) {\n\t\treturn errors.Errorf(\"column alias count %d does not match column count %d\", len(aliases), len(cols))\n\t}\n\tfor i, name := range aliases {\n\t\tcols[i].Name = normIdent(name)\n\t}\n\treturn nil\n}\n\nfunc (q *omniQuerySpanExtractor) cloneForSubquery() *omniQuerySpanExtractor {\n\tclone := &omniQuerySpanExtractor{\n\t\tquerySpanExtractor: &querySpanExtractor{\n\t\t\tctx:                 q.ctx,\n\t\t\tdefaultDatabase:     q.defaultDatabase,\n\t\t\tdefaultSchema:       q.defaultSchema,\n\t\t\tignoreCaseSensitive: q.ignoreCaseSensitive,\n\t\t\tgCtx:                q.gCtx,\n\t\t\tctes:                append([]*base.PseudoTable{}, q.ctes...),\n\t\t\touterTableSources:   append(append([]base.TableSource{}, q.outerTableSources...), q.tableSourcesFrom...),\n\t\t\tpredicateColumns:    make(base.SourceColumnSet),","sourceCodeStart":888,"sourceCodeEnd":924,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/parser/tsql/query_span_extractor_omni.go#L888-L924","documentation":"applyColumnAliases applies an explicit column alias list (e.g. the parenthesized list after a derived table, VALUES table, subquery, or table-valued function) positionally. If the alias list length differs from the number of columns the table expression produced, it errors because aliases would map onto the wrong columns.","triggerScenarios":"FROM (SELECT a, b FROM t) dt(x) — one alias for two columns; or FROM fn() f(a, b, c) where fn returns two columns; or FROM (VALUES ...) v(a, b) with mismatched arity.","commonSituations":"SQL edited so the inner SELECT list changed without updating the derived table's alias list; generated SQL templates with fixed alias headers and dynamic inner queries.","solutions":["Provide exactly one alias per column of the inner expression","Alias columns inline in the inner SELECT and drop the outer alias list","Check the table-valued function's actual return columns and update the alias list"],"exampleFix":"// before\nFROM (SELECT a, b FROM t) dt(x)\n// after\nFROM (SELECT a, b FROM t) dt(x, y)","handlingStrategy":"validation","validationCode":"// Validate derived-table alias count before extraction:\nfunc checkAliasCount(aliases []string, colCount int) error {\n\tif len(aliases) != 0 && len(aliases) != colCount {\n\t\treturn fmt.Errorf(\"%d aliases for %d columns\", len(aliases), colCount)\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Update derived-table alias lists whenever the inner SELECT list changes","Alias columns inline in the inner query and omit the positional list","Generate alias lists programmatically from the inner column list"],"tags":["sql","aliases","tsql","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}