aboutsummaryrefslogtreecommitdiff
path: root/internal/postgres
diff options
context:
space:
mode:
Diffstat (limited to 'internal/postgres')
-rw-r--r--internal/postgres/package_symbol.go94
1 files changed, 91 insertions, 3 deletions
diff --git a/internal/postgres/package_symbol.go b/internal/postgres/package_symbol.go
index aaa28267..4d99b07c 100644
--- a/internal/postgres/package_symbol.go
+++ b/internal/postgres/package_symbol.go
@@ -8,6 +8,7 @@ import (
"context"
"database/sql"
"fmt"
+ "sort"
"github.com/Masterminds/squirrel"
"golang.org/x/pkgsite/internal"
@@ -16,6 +17,93 @@ import (
"golang.org/x/pkgsite/internal/middleware/stats"
)
+// GetSymbols returns all of the symbols for a given package path and module path.
+func (db *DB) GetSymbols(ctx context.Context, pkgPath, modulePath, version string, bc internal.BuildContext) (_ []*internal.Symbol, err error) {
+ defer derrors.Wrap(&err, "DB.GetSymbols(ctx, %q, %q, %q, %v)", pkgPath, modulePath, version, bc)
+ defer stats.Elapsed(ctx, "DB.GetSymbols")()
+
+ query := packageSymbolQueryJoin(
+ squirrel.Select(
+ "s1.name AS symbol_name",
+ "s2.name AS parent_symbol_name",
+ "ps.section",
+ "ps.type",
+ "ps.synopsis",
+ "d.goos",
+ "d.goarch"), pkgPath, modulePath).
+ Where(squirrel.Eq{"m.version": version}).
+ 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
+ }
+
+ resultsByBC := make(map[internal.BuildContext][]internal.SymbolMeta)
+ collect := func(rows *sql.Rows) error {
+ var (
+ name, parentName, synopsis, goos, goarch string
+ section internal.SymbolSection
+ kind internal.SymbolKind
+ )
+ if err := rows.Scan(&name, &parentName, &section, &kind, &synopsis, &goos, &goarch); err != nil {
+ return fmt.Errorf("row.Scan(): %v", err)
+ }
+ rowBC := internal.BuildContext{GOOS: goos, GOARCH: goarch}
+ if bc.Match(rowBC) {
+ resultsByBC[rowBC] = append(resultsByBC[rowBC], internal.SymbolMeta{
+ Name: name,
+ ParentName: parentName,
+ Section: section,
+ Kind: kind,
+ Synopsis: synopsis,
+ })
+ }
+ return nil
+ }
+
+ if err := db.db.RunQuery(ctx, q, collect, args...); err != nil {
+ return nil, err
+ }
+
+ if len(resultsByBC) == 0 {
+ return nil, derrors.NotFound
+ }
+
+ // Find the best build context among those that matched.
+ var matchedBCs []internal.BuildContext
+ for b := range resultsByBC {
+ matchedBCs = append(matchedBCs, b)
+ }
+ sort.Slice(matchedBCs, func(i, j int) bool {
+ return internal.CompareBuildContexts(matchedBCs[i], matchedBCs[j]) < 0
+ })
+ bestBC := matchedBCs[0]
+
+ var symbols []*internal.Symbol
+ symbolMap := make(map[string]*internal.Symbol)
+ rows := resultsByBC[bestBC]
+ for i := range rows {
+ sm := rows[i]
+ if sm.ParentName != "" && sm.ParentName != sm.Name {
+ if parent, ok := symbolMap[sm.ParentName]; ok {
+ parent.Children = append(parent.Children, &rows[i])
+ continue
+ }
+ }
+ // Treat as top-level if no parent or parent not found in this build context.
+ s := &internal.Symbol{
+ SymbolMeta: sm,
+ GOOS: bestBC.GOOS,
+ GOARCH: bestBC.GOARCH,
+ }
+ symbols = append(symbols, s)
+ symbolMap[sm.Name] = s
+ }
+ return symbols, nil
+}
+
// 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) {
@@ -32,6 +120,8 @@ func getPackageSymbols(ctx context.Context, ddb *database.DB, packagePath, modul
"m.version",
"d.goos",
"d.goarch"), packagePath, modulePath).
+ Where("NOT m.incompatible").
+ Where(squirrel.Eq{"m.version_type": "release"}).
OrderBy("CASE WHEN ps.type='Type' THEN 0 ELSE 1 END").
OrderBy("s1.name")
q, args, err := query.PlaceholderFormat(squirrel.Dollar).ToSql()
@@ -64,9 +154,7 @@ func packageSymbolQueryJoin(query squirrel.SelectBuilder, pkgPath, modulePath st
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"})
+ Where(squirrel.Eq{"m.module_path": modulePath})
}
func collectSymbolHistory(check func(sh *internal.SymbolHistory, sm internal.SymbolMeta, v string, build internal.BuildContext) error) (*internal.SymbolHistory, func(rows *sql.Rows) error) {