internal: change GetSymbolHistoryForBuildContext output

GetSymbolHistoryForBuildContext now returns a map for nameToVersion,
instead of a full symbol history containing UnitSymbols. This function
is only used to output data for the main page, and the other information
was not used.

For golang/go#37102

Change-Id: I884dbef3b191d3cdc163ec1ab26f86dcf5a2b5ce
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/316190
Trust: Julie Qiu <julie@golang.org>
Run-TryBot: Julie Qiu <julie@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/internal/frontend/main.go b/internal/frontend/main.go
index 59b1909..2514415 100644
--- a/internal/frontend/main.go
+++ b/internal/frontend/main.go
@@ -13,12 +13,10 @@
 	"golang.org/x/mod/semver"
 	"golang.org/x/pkgsite/internal"
 	"golang.org/x/pkgsite/internal/derrors"
-	"golang.org/x/pkgsite/internal/experiment"
 	"golang.org/x/pkgsite/internal/godoc"
 	"golang.org/x/pkgsite/internal/godoc/dochtml"
 	"golang.org/x/pkgsite/internal/log"
 	"golang.org/x/pkgsite/internal/middleware"
-	"golang.org/x/pkgsite/internal/postgres"
 	"golang.org/x/pkgsite/internal/version"
 )
 
@@ -141,7 +139,6 @@
 		doc = unit.Documentation[0]
 	}
 
-	versionToNameToUnitSymbol := map[string]map[string]*internal.UnitSymbol{}
 	if doc != nil {
 		synopsis = doc.Synopsis
 		goos = doc.GOOS
@@ -160,25 +157,7 @@
 			return nil, err
 		}
 
-		if experiment.IsActive(ctx, internal.ExperimentSymbolHistoryMainPage) {
-			db, ok := ds.(*postgres.DB)
-			if !ok {
-				return nil, proxydatasourceNotSupportedErr()
-			}
-			versionToNameToUnitSymbol, err = db.GetSymbolHistoryForBuildContext(ctx, um.Path,
-				um.ModulePath, internal.BuildContext{GOOS: goos, GOARCH: goarch})
-			if err != nil {
-				return nil, err
-			}
-		}
-		nameToVersion := map[string]string{}
-		for v, nts := range versionToNameToUnitSymbol {
-			for n := range nts {
-				nameToVersion[n] = v
-			}
-		}
-
-		docParts, err = getHTML(ctx, unit, docPkg, nameToVersion)
+		docParts, err = getHTML(ctx, unit, docPkg, unit.SymbolHistory)
 		// If err  is ErrTooLarge, then docBody will have an appropriate message.
 		if err != nil && !errors.Is(err, dochtml.ErrTooLarge) {
 			return nil, err
diff --git a/internal/postgres/symbol_history.go b/internal/postgres/symbol_history.go
index 61f3d8f..06df457 100644
--- a/internal/postgres/symbol_history.go
+++ b/internal/postgres/symbol_history.go
@@ -38,7 +38,7 @@
 // GetSymbolHistoryFromTable is exported for use in tests.
 func GetSymbolHistoryFromTable(ctx context.Context, ddb *database.DB,
 	packagePath, modulePath string, bc *internal.BuildContext) (_ map[string]map[string]*internal.UnitSymbol, err error) {
-	defer derrors.WrapStack(&err, "getSymbolHistory(ctx, ddb, %q, %q)", packagePath, modulePath)
+	defer derrors.WrapStack(&err, "GetSymbolHistoryFromTable(ctx, ddb, %q, %q)", packagePath, modulePath)
 
 	q := squirrel.Select(
 		"s1.name AS symbol_name",
@@ -120,21 +120,34 @@
 	return symbol.IntroducedHistory(versionToNameToUnitSymbols), nil
 }
 
-// GetSymbolHistory returns a map of the first version when a symbol name is
+// GetSymbolHistoryForBuildContext returns a map of the first version when a symbol name is
 // added to the API for the specified build context, to the symbol name, to the
 // UnitSymbol struct. The UnitSymbol.Children field will always be empty, as
 // children names are also tracked.
 func (db *DB) GetSymbolHistoryForBuildContext(ctx context.Context, packagePath, modulePath string,
-	build internal.BuildContext) (_ map[string]map[string]*internal.UnitSymbol, err error) {
+	build internal.BuildContext) (nameToVersion map[string]string, err error) {
 	defer derrors.Wrap(&err, "GetSymbolHistoryForBuildContext(ctx, %q, %q)", packagePath, modulePath)
 	defer middleware.ElapsedStat(ctx, "GetSymbolHistoryForBuildContext")()
 
+	var versionToNameToUnitSymbol map[string]map[string]*internal.UnitSymbol
 	if experiment.IsActive(ctx, internal.ExperimentReadSymbolHistory) {
 		if build.GOOS == internal.All {
 			// It doesn't matter which one we use, so just pick a random one.
 			build = internal.BuildContextLinux
 		}
-		return GetSymbolHistoryFromTable(ctx, db.db, packagePath, modulePath, &build)
+		versionToNameToUnitSymbol, err = GetSymbolHistoryFromTable(ctx, db.db, packagePath, modulePath, &build)
+	} else {
+		versionToNameToUnitSymbol, err = GetSymbolHistoryWithPackageSymbols(ctx, db.db, packagePath, modulePath)
 	}
-	return GetSymbolHistoryWithPackageSymbols(ctx, db.db, packagePath, modulePath)
+	if err != nil {
+		return nil, err
+	}
+
+	nameToVersion = map[string]string{}
+	for v, nts := range versionToNameToUnitSymbol {
+		for n := range nts {
+			nameToVersion[n] = v
+		}
+	}
+	return nameToVersion, nil
 }
diff --git a/internal/postgres/symbol_test.go b/internal/postgres/symbol_test.go
index cab7c56..8bc7218 100644
--- a/internal/postgres/symbol_test.go
+++ b/internal/postgres/symbol_test.go
@@ -404,39 +404,17 @@
 		t.Fatalf("mismatch on symbol history(-want +got):\n%s", diff)
 	}
 
-	gotHist, err = testDB.GetSymbolHistoryForBuildContext(ctx,
+	gotHist2, err := testDB.GetSymbolHistoryForBuildContext(ctx,
 		mod10.Packages()[0].Path, mod10.ModulePath, internal.BuildContextWindows)
 	if err != nil {
 		t.Fatal(err)
 	}
-	wantHist = map[string]map[string]*internal.UnitSymbol{
-		"v1.0.0": map[string]*internal.UnitSymbol{
-			"Foo": func() *internal.UnitSymbol {
-				us := unitSymbolFromSymbol(&typ, "v1.0.0")
-				us.RemoveBuildContexts()
-				us.AddBuildContext(internal.BuildContextWindows)
-				return us
-			}(),
-		},
-		"v1.1.0": map[string]*internal.UnitSymbol{
-			"Foo.A": func() *internal.UnitSymbol {
-				us := unitSymbolFromSymbol(&methodA, "v1.1.0")
-				us.RemoveBuildContexts()
-				us.AddBuildContext(internal.BuildContextWindows)
-				return us
-			}(),
-		},
-		"v1.2.0": map[string]*internal.UnitSymbol{
-			"Foo.B": func() *internal.UnitSymbol {
-				us := unitSymbolFromSymbol(&methodB, "v1.2.0")
-				us.RemoveBuildContexts()
-				us.AddBuildContext(internal.BuildContextWindows)
-				return us
-			}(),
-		},
+	wantHist2 := map[string]string{
+		"Foo":   "v1.0.0",
+		"Foo.A": "v1.1.0",
+		"Foo.B": "v1.2.0",
 	}
-	if diff := cmp.Diff(wantHist, gotHist,
-		cmp.AllowUnexported(internal.UnitSymbol{})); diff != "" {
+	if diff := cmp.Diff(wantHist2, gotHist2); diff != "" {
 		t.Fatalf("mismatch on symbol history(-want +got):\n%s", diff)
 	}
 }
diff --git a/internal/postgres/unit.go b/internal/postgres/unit.go
index 687fcc7..d19f72a 100644
--- a/internal/postgres/unit.go
+++ b/internal/postgres/unit.go
@@ -16,6 +16,7 @@
 	"golang.org/x/pkgsite/internal"
 	"golang.org/x/pkgsite/internal/database"
 	"golang.org/x/pkgsite/internal/derrors"
+	"golang.org/x/pkgsite/internal/experiment"
 	"golang.org/x/pkgsite/internal/middleware"
 	"golang.org/x/pkgsite/internal/stdlib"
 	"golang.org/x/pkgsite/internal/version"
@@ -510,6 +511,13 @@
 	}
 	u.Subdirectories = pkgs
 	u.UnitMeta = *um
+
+	if experiment.IsActive(ctx, internal.ExperimentSymbolHistoryMainPage) {
+		u.SymbolHistory, err = db.GetSymbolHistoryForBuildContext(ctx, um.Path, um.ModulePath, bcMatched)
+		if err != nil {
+			return nil, err
+		}
+	}
 	return &u, nil
 }
 
diff --git a/internal/unit.go b/internal/unit.go
index 325fd55..db131f0 100644
--- a/internal/unit.go
+++ b/internal/unit.go
@@ -53,6 +53,10 @@
 	Symbols         map[BuildContext][]*Symbol
 	NumImports      int
 	NumImportedBy   int
+
+	// SymbolHistory is a map of symbolName to the version when the symbol was
+	// first added to the package.
+	SymbolHistory map[string]string
 }
 
 // Documentation is the rendered documentation for a given package