blob: fcebeb3d8a365dd0529b02a3a15eb7f39fffd44b [file] [log] [blame]
// 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 (
"context"
"database/sql"
"fmt"
"golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/database"
"golang.org/x/pkgsite/internal/derrors"
"golang.org/x/pkgsite/internal/middleware"
)
// getPackageSymbols returns all of the symbols for a given package path and module path.
func getPackageSymbols(ctx context.Context, ddb *database.DB, packagePath, modulePath string,
) (_ *internal.SymbolHistory, err error) {
defer derrors.Wrap(&err, "getPackageSymbols(ctx, ddb, %q, %q)", packagePath, modulePath)
defer middleware.ElapsedStat(ctx, "getPackageSymbols")()
query := `
SELECT
s1.name AS symbol_name,
s2.name AS parent_symbol_name,
ps.section,
ps.type,
ps.synopsis,
m.version,
d.goos,
d.goarch
FROM modules m
INNER JOIN units u ON u.module_id = m.id
INNER JOIN documentation d ON d.unit_id = u.id
INNER JOIN documentation_symbols ds ON ds.documentation_id = d.id
INNER JOIN package_symbols ps ON ps.id = ds.package_symbol_id
INNER JOIN paths p1 ON u.path_id = p1.id
INNER JOIN symbol_names s1 ON ps.symbol_name_id = s1.id
INNER JOIN symbol_names s2 ON ps.parent_symbol_name_id = s2.id
WHERE
p1.path = $1
AND m.module_path = $2
AND NOT m.incompatible
AND m.version_type = 'release'
ORDER BY
CASE WHEN ps.type='Type' THEN 0 ELSE 1 END,
symbol_name;`
sh, collect := collectSymbolHistory(func(sh *internal.SymbolHistory, sm internal.SymbolMeta, v string, build internal.BuildContext) error {
if sm.Section == internal.SymbolSectionTypes && sm.Kind != internal.SymbolKindType {
_, err := sh.GetSymbol(sm.ParentName, v, build)
if err != nil {
return fmt.Errorf("could not find parent for %q: %v", sm.Name, err)
}
return nil
}
return nil
})
if err := ddb.RunQuery(ctx, query, collect, packagePath, modulePath); err != nil {
return nil, err
}
return sh, nil
}
func collectSymbolHistory(check func(sh *internal.SymbolHistory, sm internal.SymbolMeta, v string, build internal.BuildContext) error) (*internal.SymbolHistory, func(rows *sql.Rows) error) {
sh := internal.NewSymbolHistory()
return sh, func(rows *sql.Rows) (err error) {
defer derrors.Wrap(&err, "collectSymbolHistory")
var (
sm internal.SymbolMeta
build internal.BuildContext
v string
)
if err := rows.Scan(
&sm.Name,
&sm.ParentName,
&sm.Section,
&sm.Kind,
&sm.Synopsis,
&v,
&build.GOOS,
&build.GOARCH,
); err != nil {
return fmt.Errorf("row.Scan(): %v", err)
}
if err := check(sh, sm, v, build); err != nil {
return fmt.Errorf("check(): %v", err)
}
sh.AddSymbol(sm, v, build)
return nil
}
}