// Copyright 2019 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"
	"sort"
	"strings"

	"github.com/Masterminds/squirrel"
	"github.com/lib/pq"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/database"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/licenses"
	"golang.org/x/pkgsite/internal/middleware/stats"
	"golang.org/x/pkgsite/internal/stdlib"
	"golang.org/x/pkgsite/internal/version"
)

// GetUnitMeta returns information about the "best" entity (module, path or directory) with
// the given path. The module and version arguments provide additional constraints.
// If the module is unknown, pass internal.UnknownModulePath; if the version is unknown, pass
// internal.LatestVersion.
//
// The rules for picking the best are as follows.
//
// 1. If the version is known but the module path is not, choose the longest module path
// at that version that contains fullPath.
//
// 2. Otherwise, find the latest "good" version (in the modules table) that contains fullPath.
//
//	a. First, follow the algorithm of the go command: prefer longer module paths, and
//	   find the latest unretracted version, using semver but preferring release to pre-release.
//	b. If no modules have latest-version information, find the latest by sorting the versions
//	   we do have: again first by module path length, then by version.
func (db *DB) GetUnitMeta(ctx context.Context, fullPath, requestedModulePath, requestedVersion string) (_ *internal.UnitMeta, err error) {
	defer derrors.WrapStack(&err, "DB.GetUnitMeta(ctx, %q, %q, %q)", fullPath, requestedModulePath, requestedVersion)
	defer stats.Elapsed(ctx, "DB.GetUnitMeta")()

	modulePath := requestedModulePath
	v := requestedVersion
	var lmv *internal.LatestModuleVersions
	if requestedVersion == version.Latest {
		modulePath, v, lmv, err = db.getLatestUnitVersion(ctx, fullPath, requestedModulePath)
		if err != nil {
			return nil, err
		}
	}
	return db.getUnitMetaWithKnownVersion(ctx, fullPath, modulePath, v, lmv)
}

func (db *DB) getUnitMetaWithKnownVersion(ctx context.Context, fullPath, modulePath, version string, lmv *internal.LatestModuleVersions) (_ *internal.UnitMeta, err error) {
	defer derrors.WrapStack(&err, "getUnitMetaWithKnownVersion")
	defer stats.Elapsed(ctx, "getUnitMetaWithKnownVersion")()

	query := squirrel.Select(
		"m.module_path",
		"m.version",
		"m.commit_time",
		"m.source_info",
		"m.has_go_mod",
		"m.redistributable",
		"u.name").
		From("modules m").
		Join("units u on u.module_id = m.id").
		Join("paths p ON p.id = u.path_id").Where(squirrel.Eq{"p.path": fullPath}).
		PlaceholderFormat(squirrel.Dollar)

	if internal.DefaultBranches[version] || stdlib.SupportedBranches[version] {
		query = query.
			Join("version_map vm ON m.id = vm.module_id").
			Where("vm.requested_version = ?", version)
	} else {
		query = query.Where(squirrel.Eq{"version": version})
	}
	if modulePath == internal.UnknownModulePath {
		candidates := internal.CandidateModulePaths(fullPath)
		// If we don't know the module, look for the one  with the longest series path.
		query = query.Where(squirrel.Eq{"m.module_path": candidates}).
			OrderBy("m.series_path DESC").
			Limit(1)
	} else {
		query = query.Where(squirrel.Eq{"m.module_path": modulePath})
	}

	q, args, err := query.ToSql()
	if err != nil {
		return nil, err
	}
	var (
		um = internal.UnitMeta{Path: fullPath}
	)
	err = db.db.QueryRow(ctx, q, args...).Scan(
		&um.ModulePath,
		&um.Version,
		&um.CommitTime,
		jsonbScanner{&um.SourceInfo},
		&um.HasGoMod,
		&um.ModuleInfo.IsRedistributable,
		&um.Name)
	if err == sql.ErrNoRows {
		return nil, derrors.NotFound
	}
	if err != nil {
		return nil, err
	}

	// If we don't have the latest version information, try to get it.
	// We can be here if there is really no info (in which case we are repeating
	// some work, but it's fast), or if we are ignoring the info (for instance,
	// if all versions were retracted).
	if lmv == nil {
		lmv, err = db.GetLatestModuleVersions(ctx, um.ModulePath)
		if err != nil {
			return nil, err
		}
	}
	if lmv != nil {
		lmv.PopulateModuleInfo(&um.ModuleInfo)
	}
	return &um, nil
}

// getLatestUnitVersion gets the latest version of requestedModulePath that contains fullPath.
// See GetUnitMeta for more details.
func (db *DB) getLatestUnitVersion(ctx context.Context, fullPath, requestedModulePath string) (
	modulePath, latestVersion string, lmv *internal.LatestModuleVersions, err error) {

	defer derrors.WrapStack(&err, "getLatestUnitVersion(%q, %q)", fullPath, requestedModulePath)
	defer stats.Elapsed(ctx, "getLatestUnitVersion")()

	modPaths := []string{requestedModulePath}
	// If we don't know the module path, try each possible module path from longest to shortest.
	if requestedModulePath == internal.UnknownModulePath {
		modPaths = internal.CandidateModulePaths(fullPath)
	}
	// Get latest-version information for all possible modules, from longest
	// to shortest path.
	lmvs, err := db.getMultiLatestModuleVersions(ctx, modPaths)
	if err != nil {
		return "", "", nil, err
	}
	for _, lmv = range lmvs {
		// Collect all the versions of this module that contain fullPath.
		query := squirrel.Select("m.version").
			From("modules m").
			Join("units u on u.module_id = m.id").
			Join("paths p ON p.id = u.path_id").
			Where(squirrel.Eq{"m.module_path": lmv.ModulePath}).
			Where(squirrel.Eq{"p.path": fullPath})
		q, args, err := query.PlaceholderFormat(squirrel.Dollar).ToSql()
		if err != nil {
			return "", "", nil, err
		}
		allVersions, err := database.Collect1[string](ctx, db.db, q, args...)
		if err != nil {
			return "", "", nil, err
		}
		// Remove retracted versions.
		unretractedVersions := version.RemoveIf(allVersions, lmv.IsRetracted)
		// If there are no unretracted versions, move on. If we fall out of the
		// loop we will pick the latest retracted version.
		if len(unretractedVersions) == 0 {
			continue
		}
		// Choose the latest version.
		// If the cooked latest version is compatible, then by the logic of
		// internal/version.Latest (which matches the go command), either
		// incompatible versions should be ignored or there were no incompatible
		// versions. In either case, remove them.
		if !version.IsIncompatible(lmv.CookedVersion) {
			unretractedVersions = version.RemoveIf(unretractedVersions, version.IsIncompatible)
		}
		// The good version should never be later than the cooked version.
		// https://golang.org/issue/43265 documents how that could happen:
		// 1. A pseudo-version is created off of a tagged version. In this case,
		//    golang.zx2c4.com/wireguard@v0.0.20201119-0.20210128142622-6a128dde71d9.
		// 2. All tagged versions are retracted.
		// 3. A new pseudo-version is published. In this case, v0.0.0-20210506092213-60a26371f42f.
		// Technically, the first pseudo-version is higher than the second, so it
		// is the latest good version. But the proxy's latest endpoint returns
		// the second pseudo-version, so that is the cooked version (and what the
		// go command will download).
		if lmv.CookedVersion != "" {
			unretractedVersions = version.RemoveIf(unretractedVersions, func(v string) bool {
				return version.Later(v, lmv.CookedVersion)
			})
		}
		latestVersion = version.LatestOf(unretractedVersions)
		break
	}
	if latestVersion != "" {
		return lmv.ModulePath, latestVersion, lmv, nil
	}
	// If we don't have latest-version info for any path (or there are no
	// unretracted versions for paths where we do), fall back to finding the
	// latest good version from the longest path. We can't determine
	// deprecations or retractions, and the "go get" command won't download the
	// module unless a specific version is supplied. But we can still show the
	// latest version we have.
	query := squirrel.Select("m.module_path", "m.version").
		From("modules m").
		Join("units u on u.module_id = m.id").
		Join("paths p ON p.id = u.path_id").
		Where(squirrel.Eq{"p.path": fullPath}).
		// Like the go command, order first by path length, then by release
		// version, then prerelease. Without latest-version information, we
		// ignore all adjustments for incompatible and retracted versions.
		OrderBy("m.series_path DESC", "m.version_type = 'release' DESC", "m.sort_version DESC").
		Limit(1)
	q, args, err := query.PlaceholderFormat(squirrel.Dollar).ToSql()
	if err != nil {
		return "", "", nil, err
	}
	err = db.db.QueryRow(ctx, q, args...).Scan(&modulePath, &latestVersion)
	if err == sql.ErrNoRows {
		return "", "", nil, derrors.NotFound
	}
	if err != nil {
		return "", "", nil, err
	}
	return modulePath, latestVersion, nil, nil
}

// GetUnit returns a unit from the database, along with all of the data
// associated with that unit.
// If bc is not nil, get only the Documentation that matches it (or nil if none do).
func (db *DB) GetUnit(ctx context.Context, um *internal.UnitMeta, fields internal.FieldSet, bc internal.BuildContext) (_ *internal.Unit, err error) {
	defer derrors.WrapStack(&err, "GetUnit(ctx, %q, %q, %q, %v)", um.Path, um.ModulePath, um.Version, bc)

	u := &internal.Unit{UnitMeta: *um}
	if fields&internal.WithMain != 0 {
		u, err = db.getUnitWithAllFields(ctx, um, fields, bc)
		if err != nil {
			return nil, err
		}
	}
	if fields&internal.WithImports == 0 &&
		fields&internal.WithLicenses == 0 {
		return u, nil
	}

	defer stats.Elapsed(ctx, "GetUnit")()
	unitID, isRedistributable, err := db.getUnitID(ctx, um.Path, um.ModulePath, um.Version)
	if err != nil {
		return nil, err
	}
	u.IsRedistributable = isRedistributable

	if fields&internal.WithImports != 0 {
		imports, err := db.getImports(ctx, unitID)
		if err != nil {
			return nil, err
		}
		if len(imports) > 0 {
			u.Imports = imports
			u.NumImports = len(imports)
		}
	}
	if fields&internal.WithLicenses != 0 {
		lics, err := db.getLicenses(ctx, u.Path, u.ModulePath, unitID)
		if err != nil {
			return nil, err
		}
		u.LicenseContents = lics
	}
	if db.bypassLicenseCheck {
		u.IsRedistributable = true
	} else {
		u.RemoveNonRedistributableData()
	}
	return u, nil
}

// GetModulePackages returns a list of packages in the given module version.
func (db *DB) GetModulePackages(ctx context.Context, modulePath, requestedVersion string) ([]*internal.PackageMeta, error) {
	resolvedVersion := requestedVersion
	if requestedVersion == version.Latest {
		lmv, err := db.GetLatestModuleVersions(ctx, modulePath)
		if err != nil {
			return nil, err
		}
		if lmv == nil {
			return nil, fmt.Errorf("%w: module %s not found", derrors.NotFound, modulePath)
		}
		resolvedVersion = lmv.GoodVersion
	}
	return getPackagesInUnit(ctx, db.db, modulePath, modulePath, resolvedVersion, -1, db.bypassLicenseCheck)
}

func (db *DB) getUnitID(ctx context.Context, fullPath, modulePath, resolvedVersion string) (_ int, _ bool, err error) {
	defer derrors.WrapStack(&err, "getUnitID(ctx, %q, %q, %q)", fullPath, modulePath, resolvedVersion)
	defer stats.Elapsed(ctx, "getUnitID")()
	var unitID int
	var isRedistributable bool
	query := `
		SELECT u.id, u.redistributable
		FROM units u
		INNER JOIN paths p ON (p.id = u.path_id)
		INNER JOIN modules m ON (u.module_id = m.id)
		WHERE
			p.path = $1
			AND m.module_path = $2
			AND m.version = $3;`
	err = db.db.QueryRow(ctx, query, fullPath, modulePath, resolvedVersion).Scan(&unitID, &isRedistributable)
	switch err {
	case sql.ErrNoRows:
		return 0, false, derrors.NotFound
	case nil:
		return unitID, isRedistributable, nil
	default:
		return 0, false, err
	}
}

// getImports returns the imports corresponding to unitID.
func (db *DB) getImports(ctx context.Context, unitID int) (_ []string, err error) {
	defer derrors.WrapStack(&err, "getImports(ctx, %d)", unitID)
	defer stats.Elapsed(ctx, "getImports")()
	query := `
		SELECT p.path
		FROM paths p INNER JOIN imports i ON p.id = i.to_path_id
		WHERE i.unit_id = $1`
	return database.Collect1[string](ctx, db.db, query, unitID)
}

// getPackagesInUnit returns all of the packages in a unit from a
// module_id, including the package that lives at fullPath, if present.
func (db *DB) getPackagesInUnit(ctx context.Context, fullPath string, moduleID int) (_ []*internal.PackageMeta, err error) {
	return getPackagesInUnit(ctx, db.db, fullPath, "", "", moduleID, db.bypassLicenseCheck)
}

func getPackagesInUnit(ctx context.Context, db *database.DB, fullPath, modulePath, resolvedVersion string, moduleID int, bypassLicenseCheck bool) (_ []*internal.PackageMeta, err error) {
	defer derrors.WrapStack(&err, "getPackagesInUnit(ctx, %q, %q, %q, %d)", fullPath, modulePath, resolvedVersion, moduleID)
	defer stats.Elapsed(ctx, "getPackagesInUnit")()

	queryBuilder := squirrel.Select(
		"p.path",
		"u.name",
		"u.redistributable",
		"d.synopsis",
		"d.GOOS",
		"d.GOARCH",
		"u.license_types",
		"u.license_paths",
	).From("units u")

	if moduleID != -1 {
		queryBuilder = queryBuilder.Join("paths p ON p.id = u.path_id").
			LeftJoin("documentation d ON d.unit_id = u.id").
			Where(squirrel.Eq{"u.module_id": moduleID})
	} else {
		queryBuilder = queryBuilder.
			Join("modules m ON u.module_id = m.id").
			Join("paths p ON p.id = u.path_id").
			LeftJoin("documentation d ON d.unit_id = u.id").
			Where(squirrel.Eq{"m.module_path": modulePath}).
			Where(squirrel.Eq{"m.version": resolvedVersion})
	}

	queryBuilder = queryBuilder.Where(squirrel.NotEq{"u.name": ""})

	query, args, err := queryBuilder.PlaceholderFormat(squirrel.Dollar).ToSql()
	if err != nil {
		return nil, err
	}

	// If a package has more than build context (GOOS/GOARCH pair), it will have
	// more than one row in documentation, and this query will produce multiple
	// rows for that package. If we could sort the build contexts in SQL we
	// could deal with that in the query, but we must sort in code, so we read
	// all the rows and pick the right one afterwards.
	type pmbc struct {
		pm *internal.PackageMeta
		bc internal.BuildContext
	}
	packagesByPath := map[string][]pmbc{}
	collect := func(rows *sql.Rows) error {
		var (
			pkg          internal.PackageMeta
			licenseTypes []string
			licensePaths []string
			bc           internal.BuildContext
		)
		if err := rows.Scan(
			&pkg.Path,
			&pkg.Name,
			&pkg.IsRedistributable,
			database.NullIsEmpty(&pkg.Synopsis),
			database.NullIsEmpty(&bc.GOOS),
			database.NullIsEmpty(&bc.GOARCH),
			pq.Array(&licenseTypes),
			pq.Array(&licensePaths),
		); err != nil {
			return fmt.Errorf("row.Scan(): %v", err)
		}
		if fullPath == stdlib.ModulePath || pkg.Path == fullPath || strings.HasPrefix(pkg.Path, fullPath+"/") {
			lics, err := zipLicenseMetadata(licenseTypes, licensePaths)
			if err != nil {
				return err
			}
			pkg.Licenses = lics
			packagesByPath[pkg.Path] = append(packagesByPath[pkg.Path], pmbc{&pkg, bc})
		}
		return nil
	}
	if err := db.RunQuery(ctx, query, collect, args...); err != nil {
		return nil, err
	}
	if len(packagesByPath) == 0 {
		return nil, derrors.NotFound
	}
	var packages []*internal.PackageMeta
	for _, ps := range packagesByPath {
		sort.Slice(ps, func(i, j int) bool { return internal.CompareBuildContexts(ps[i].bc, ps[j].bc) < 0 })
		packages = append(packages, ps[0].pm)
	}
	sort.Slice(packages, func(i, j int) bool { return packages[i].Path < packages[j].Path })
	for _, p := range packages {
		if bypassLicenseCheck {
			p.IsRedistributable = true
		} else {
			p.RemoveNonRedistributableData()
		}
	}
	return packages, nil
}

// unitContext contains information for a unit that is used to fetch its
// documentation or symbols.
type unitContext struct {
	unitID            int
	pathID            int
	moduleID          int
	isRedistributable bool
	bcs               []internal.BuildContext
	bestBC            internal.BuildContext
	docID             int
	licenseMetas      []*licenses.Metadata
}

// getUnitContext returns a unitContext for the given package path, module path,
// version and build context. It finds all available build contexts for the
// unit, selects the best matching one, and identifies the corresponding
// documentation ID.
func (db *DB) getUnitContext(ctx context.Context, pkgPath, modulePath, version string, bc internal.BuildContext) (_ *unitContext, err error) {
	defer derrors.WrapStack(&err, "getUnitContext(ctx, %q, %q, %q, %v)", pkgPath, modulePath, version, bc)

	var (
		uc = &unitContext{}
		// Map from build context to documentation ID.
		docIDs = make(map[internal.BuildContext]int)
	)
	err = db.db.RunQuery(ctx, `
		SELECT d.goos, d.goarch, u.id, p.id, u.module_id, u.license_types, u.license_paths, u.redistributable, d.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 (
			rowBC internal.BuildContext
			docID sql.NullInt64
		)

		// We need to scan all columns, but some are unit-level (constant across rows)
		// and some are documentation-level (vary across rows).
		var (
			uIDCol, pIDCol, mIDCol   int
			licTypesCol, licPathsCol []string
			isRedistCol              bool
		)

		if err := rows.Scan(
			database.NullIsEmpty(&rowBC.GOOS),
			database.NullIsEmpty(&rowBC.GOARCH),
			&uIDCol,
			&pIDCol,
			&mIDCol,
			pq.Array(&licTypesCol),
			pq.Array(&licPathsCol),
			&isRedistCol,
			&docID,
		); err != nil {
			return err
		}

		// Assign unit-level metadata only once.
		if uc.unitID == 0 {
			uc.unitID = uIDCol
			uc.pathID = pIDCol
			uc.moduleID = mIDCol
			uc.isRedistributable = isRedistCol
			if db.bypassLicenseCheck {
				uc.isRedistributable = true
			}
			lics, err := zipLicenseMetadata(licTypesCol, licPathsCol)
			if err != nil {
				return err
			}
			uc.licenseMetas = lics
		}

		if rowBC.GOOS != "" && rowBC.GOARCH != "" {
			uc.bcs = append(uc.bcs, rowBC)
			if docID.Valid {
				docIDs[rowBC] = int(docID.Int64)
			}
		}
		return nil
	}, pkgPath, modulePath, version)
	if err != nil {
		return nil, err
	}
	if uc.unitID == 0 {
		return nil, derrors.NotFound
	}

	uc.bcs = internal.SortedBuildContexts(uc.bcs)

	var ok bool
	uc.bestBC, ok = internal.MatchingBuildContext(uc.bcs, bc)
	if ok {
		uc.docID = docIDs[uc.bestBC]
	}
	return uc, nil
}

func (db *DB) getUnitWithAllFields(ctx context.Context, um *internal.UnitMeta, fields internal.FieldSet, bc internal.BuildContext) (_ *internal.Unit, err error) {
	defer derrors.WrapStack(&err, "getUnitWithAllFields(ctx, %q, %q, %q)", um.Path, um.ModulePath, um.Version)
	defer stats.Elapsed(ctx, "getUnitWithAllFields")()

	uc, err := db.getUnitContext(ctx, um.Path, um.ModulePath, um.Version, bc)
	if err != nil {
		return nil, err
	}

	docSelect := "CAST(NULL AS bytea),"
	if fields&internal.WithDocsSource != 0 {
		docSelect = "d.source,"
	}

	query := fmt.Sprintf(`
        SELECT
			r.file_path,
			r.contents,
			d.synopsis,
			%s
			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 documentation d
		ON d.id = $3
		WHERE u.id = $2
	`, docSelect)
	var (
		r internal.Readme
		u internal.Unit
	)
	u.BuildContexts = uc.bcs
	doc := &internal.Documentation{GOOS: uc.bestBC.GOOS, GOARCH: uc.bestBC.GOARCH}
	end := stats.Elapsed(ctx, "getUnitWithAllFields-readme-and-imports")
	var docID any
	if uc.docID != 0 {
		docID = uc.docID
	}
	err = db.db.QueryRow(ctx, query, uc.pathID, uc.unitID, docID).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, uc.moduleID)
	if err != nil {
		return nil, err
	}
	u.Subdirectories = pkgs
	u.UnitMeta = *um
	u.Licenses = uc.licenseMetas
	u.IsRedistributable = uc.isRedistributable

	if um.IsPackage() && !um.IsCommand() && uc.bestBC.GOOS != "" {
		u.SymbolHistory, err = GetSymbolHistoryForBuildContext(ctx, db.db, uc.pathID, um.ModulePath, uc.bestBC)
		if err != nil {
			return nil, err
		}
	}
	return &u, nil
}

type dbPath struct {
	id              int64
	path            string
	moduleID        int64
	name            string
	licenseTypes    []string
	licensePaths    []string
	redistributable bool
}

func (db *DB) getPathsInModule(ctx context.Context, modulePath, resolvedVersion string) (_ []*dbPath, err error) {
	defer derrors.WrapStack(&err, "DB.getPathsInModule(ctx, %q, %q)", modulePath, resolvedVersion)
	query := `
	SELECT
		u.id,
		p.path,
		u.module_id,
		u.name,
		u.license_types,
		u.license_paths,
		u.redistributable
	FROM
		units u
	INNER JOIN
		paths p
	ON
		p.id = u.path_id
	INNER JOIN
		modules m
	ON
		u.module_id = m.id
	WHERE
		m.module_path = $1
		AND m.version = $2
	ORDER BY path;`

	var paths []*dbPath
	collect := func(rows *sql.Rows) error {
		var p dbPath
		if err := rows.Scan(&p.id, &p.path, &p.moduleID, &p.name, pq.Array(&p.licenseTypes),
			pq.Array(&p.licensePaths), &p.redistributable); err != nil {
			return fmt.Errorf("row.Scan(): %v", err)
		}
		paths = append(paths, &p)
		return nil
	}
	if err := db.db.RunQuery(ctx, query, collect, modulePath, resolvedVersion); err != nil {
		return nil, err
	}
	return paths, nil
}

// GetModuleReadme returns the README corresponding to the modulePath and version.
func (db *DB) GetModuleReadme(ctx context.Context, modulePath, resolvedVersion string) (_ *internal.Readme, err error) {
	return getModuleReadme(ctx, db.db, modulePath, resolvedVersion)
}

func getModuleReadme(ctx context.Context, db *database.DB, modulePath, resolvedVersion string) (_ *internal.Readme, err error) {
	defer derrors.WrapStack(&err, "getModuleReadme(ctx, %q, %q)", modulePath, resolvedVersion)
	var readme internal.Readme
	err = db.QueryRow(ctx, `
		SELECT file_path, contents
		FROM modules m
		INNER JOIN units u
		ON u.module_id = m.id
		INNER JOIN paths p
		ON u.path_id = p.id
		INNER JOIN readmes r
		ON u.id = r.unit_id
		WHERE
		    m.module_path=$1
			AND m.version=$2
			AND m.module_path=p.path`, modulePath, resolvedVersion).Scan(&readme.Filepath, &readme.Contents)
	switch err {
	case sql.ErrNoRows:
		return nil, derrors.NotFound
	case nil:
		return &readme, nil
	default:
		return nil, err
	}
}
