in internal/postgres/unit.go [425:547]
func (db *DB) getUnitWithAllFields(ctx context.Context, um *internal.UnitMeta, bc internal.BuildContext) (_ *internal.Unit, err error) {
defer derrors.WrapStack(&err, "getUnitWithAllFields(ctx, %q, %q, %q)", um.Path, um.ModulePath, um.Version)
defer middleware.ElapsedStat(ctx, "getUnitWithAllFields")()
// Get build contexts and unit ID.
var pathID, unitID, moduleID int
var bcs []internal.BuildContext
err = db.db.RunQuery(ctx, `
SELECT d.goos, d.goarch, u.id, p.id, u.module_id
FROM units u
INNER JOIN paths p ON p.id = u.path_id
INNER JOIN modules m ON m.id = u.module_id
LEFT JOIN documentation d ON d.unit_id = u.id
WHERE
p.path = $1
AND m.module_path = $2
AND m.version = $3
`, func(rows *sql.Rows) error {
var bc internal.BuildContext
// GOOS and GOARCH will be NULL if there are no documentation rows for
// the unit, but we still want the unit ID.
if err := rows.Scan(database.NullIsEmpty(&bc.GOOS), database.NullIsEmpty(&bc.GOARCH), &unitID, &pathID, &moduleID); err != nil {
return err
}
if bc.GOOS != "" && bc.GOARCH != "" {
bcs = append(bcs, bc)
}
return nil
}, um.Path, um.ModulePath, um.Version)
if err != nil {
return nil, err
}
sort.Slice(bcs, func(i, j int) bool { return internal.CompareBuildContexts(bcs[i], bcs[j]) < 0 })
var bcMatched internal.BuildContext
for _, c := range bcs {
if bc.Match(c) {
bcMatched = c
break
}
}
// Get README, documentation and import counts.
query := `
SELECT
r.file_path,
r.contents,
d.synopsis,
d.source,
COALESCE((
SELECT COUNT(unit_id)
FROM imports
WHERE unit_id = u.id
GROUP BY unit_id
), 0) AS num_imports,
COALESCE((
SELECT imported_by_count
FROM search_documents
-- Only package_path_id is needed b/c it is the PK for
-- search_documents.
WHERE package_path_id = $1
), 0) AS num_imported_by
FROM units u
LEFT JOIN readmes r
ON r.unit_id = u.id
LEFT JOIN (
SELECT synopsis, source, goos, goarch, unit_id
FROM documentation d
WHERE d.GOOS = $3 AND d.GOARCH = $4
) d
ON d.unit_id = u.id
WHERE u.id = $2
`
var (
r internal.Readme
u internal.Unit
)
u.BuildContexts = bcs
var goos, goarch interface{}
if bcMatched.GOOS != "" {
goos = bcMatched.GOOS
goarch = bcMatched.GOARCH
}
doc := &internal.Documentation{GOOS: bcMatched.GOOS, GOARCH: bcMatched.GOARCH}
end := middleware.ElapsedStat(ctx, "getUnitWithAllFields-readme-and-imports")
err = db.db.QueryRow(ctx, query, pathID, unitID, goos, goarch).Scan(
database.NullIsEmpty(&r.Filepath),
database.NullIsEmpty(&r.Contents),
database.NullIsEmpty(&doc.Synopsis),
&doc.Source,
&u.NumImports,
&u.NumImportedBy,
)
switch err {
case sql.ErrNoRows:
// Neither a README nor documentation; that's OK, continue.
case nil:
if r.Filepath != "" && um.ModulePath != stdlib.ModulePath {
u.Readme = &r
}
if doc.GOOS != "" {
u.Documentation = []*internal.Documentation{doc}
}
default:
return nil, err
}
end()
// Get other info.
pkgs, err := db.getPackagesInUnit(ctx, um.Path, moduleID)
if err != nil {
return nil, err
}
u.Subdirectories = pkgs
u.UnitMeta = *um
if um.IsPackage() && !um.IsCommand() && doc.Source != nil {
u.SymbolHistory, err = GetSymbolHistoryForBuildContext(ctx, db.db, pathID, um.ModulePath, bcMatched)
if err != nil {
return nil, err
}
}
return &u, nil
}