зеркало из https://github.com/golang/pkgsite.git
100 строки
3.1 KiB
Go
100 строки
3.1 KiB
Go
// 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"
|
|
|
|
"github.com/Masterminds/squirrel"
|
|
"golang.org/x/pkgsite/internal"
|
|
"golang.org/x/pkgsite/internal/database"
|
|
"golang.org/x/pkgsite/internal/derrors"
|
|
"golang.org/x/pkgsite/internal/middleware/stats"
|
|
)
|
|
|
|
// 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 stats.Elapsed(ctx, "getPackageSymbols")()
|
|
|
|
query := packageSymbolQueryJoin(
|
|
squirrel.Select(
|
|
"s1.name AS symbol_name",
|
|
"s2.name AS parent_symbol_name",
|
|
"ps.section",
|
|
"ps.type",
|
|
"ps.synopsis",
|
|
"m.version",
|
|
"d.goos",
|
|
"d.goarch"), packagePath, modulePath).
|
|
OrderBy("CASE WHEN ps.type='Type' THEN 0 ELSE 1 END").
|
|
OrderBy("s1.name")
|
|
q, args, err := query.PlaceholderFormat(squirrel.Dollar).ToSql()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
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, q, collect, args...); err != nil {
|
|
return nil, err
|
|
}
|
|
return sh, nil
|
|
}
|
|
|
|
func packageSymbolQueryJoin(query squirrel.SelectBuilder, pkgPath, modulePath string) squirrel.SelectBuilder {
|
|
return query.From("modules m").
|
|
Join("units u on u.module_id = m.id").
|
|
Join("documentation d ON d.unit_id = u.id").
|
|
Join("documentation_symbols ds ON ds.documentation_id = d.id").
|
|
Join("package_symbols ps ON ps.id = ds.package_symbol_id").
|
|
Join("paths p1 ON u.path_id = p1.id").
|
|
Join("symbol_names s1 ON ps.symbol_name_id = s1.id").
|
|
Join("symbol_names s2 ON ps.parent_symbol_name_id = s2.id").
|
|
Where(squirrel.Eq{"p1.path": pkgPath}).
|
|
Where(squirrel.Eq{"m.module_path": modulePath}).
|
|
Where("NOT m.incompatible").
|
|
Where(squirrel.Eq{"m.version_type": "release"})
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|