Copyright 2021 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package postgres

import (
	
	

	
	
	
	
	
)
upsertSymbolHistory upserts data into the symbol_history table.
func ( context.Context,  *database.DB,
	,  string,
	 map[string]int,
	 map[string]int,
	 map[string]map[packageSymbol]int,
	 map[string]map[int]*internal.Documentation,
) ( error) {
	defer derrors.WrapStack(&, "upsertSymbolHistory")

	,  := version.ParseType()
	if  != nil {
		return 
	}
	if  != version.TypeRelease || version.IsIncompatible() {
		return nil
	}

	if ,  := .Exec(, `LOCK TABLE symbol_history IN EXCLUSIVE MODE`);  != nil {
		return 
	}
	for ,  := range  {
		,  := GetSymbolHistoryFromTable(, , , )
		if  != nil {
			return 
		}
		for ,  := range  {
			var  []interface{}
			 := []internal.BuildContext{{GOOS: .GOOS, GOARCH: .GOARCH}}
			if .GOOS == internal.All {
				 = internal.BuildContexts
			}
			for ,  := range  {
				 := map[string]string{}
				for ,  := range .Versions() {
					 := .SymbolsAtVersion()
					for ,  := range  {
						for ,  := range  {
							if .SupportsBuild() {
								[] = 
							}
						}
					}
				}
				 := map[string]bool{}
While a package with duplicate symbol names won't build, the documentation for these packages are currently rendered on pkg.go.dev, so doc.API may contain more than one symbol with the same name. For the purpose of symbol_history, just use the first symbol name we see.
					if [.Name] {
						return nil
					}
					[.Name] = true

					if shouldUpdateSymbolHistory(.Name, , ) {
						,  = appendSymbolHistoryRow(, ,
							, , , , , ,
							)
						if  != nil {
							return 
						}
					}
					return nil
				});  != nil {
					return 
				}
			}

			 := []string{
				"symbol_name_id",
				"parent_symbol_name_id",
				"package_path_id",
				"module_path_id",
				"package_symbol_id",
				"since_version",
				"sort_version",
				"goos",
				"goarch",
			}
			if  := .BulkInsert(, "symbol_history", , ,
				`ON CONFLICT (package_path_id, module_path_id, symbol_name_id, goos, goarch)
				DO UPDATE
				SET
					symbol_name_id=excluded.symbol_name_id,
					parent_symbol_name_id=excluded.parent_symbol_name_id,
					package_path_id=excluded.package_path_id,
					module_path_id=excluded.module_path_id,
					package_symbol_id=excluded.package_symbol_id,
					since_version=excluded.since_version,
					sort_version=excluded.sort_version,
					goos=excluded.goos,
					goarch=excluded.goarch
				WHERE
					symbol_history.sort_version > excluded.sort_version`);  != nil {
				return 
			}
		}
	}
	return nil
}

func ( *internal.SymbolMeta,  []interface{},
	, ,  string,  internal.BuildContext,
	,  map[string]int,
	 map[string]map[packageSymbol]int) ( []interface{},  error) {
	defer derrors.WrapStack(&, "appendSymbolHistoryRow(%q, %q, %q, %q)", .Name, , , )
	 := [.Name]
	if  == 0 {
		return nil, fmt.Errorf("symbolID cannot be 0: %q", .Name)
	}
	if .ParentName == "" {
		.ParentName = .Name
	}
	 := [.ParentName]
	if  == 0 {
		return nil, fmt.Errorf("parentSymbolID cannot be 0: %q", .ParentName)
	}
	 := []
	if  == 0 {
		return nil, fmt.Errorf("packagePathID cannot be 0: %q", )
	}
	 := []
	if  == 0 {
		return nil, fmt.Errorf("modulePathID cannot be 0: %q", )
	}
	 := [][packageSymbol{synopsis: .Synopsis, name: .Name, parentName: .ParentName}]
	return append(,
		,
		,
		,
		,
		,
		,
		version.ForSorting(),
		.GOOS,
		.GOARCH), nil
}
shouldUpdateSymbolHistory reports whether the row for the given symbolName should be updated. oldHist contains all of the current symbols in the database for the same package and GOOS/GOARCH. shouldUpdateSymbolHistory reports true if the symbolName does not currently exist, or if the newVersion is older than or equal to the current database version.
func (,  string,  map[string]string) bool {
	,  := []
	if ! {
		return true
	}
	return semver.Compare(, ) <= 0