internal/postgres: add GetLatestMinorModuleVersion
Add a method that returns the latest minor version of a module,
and whether a unit exists in that version.
For golang/go#37631
Change-Id: I3f612b5df561c39831494388bb37bc6ee9096168
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/279460
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/postgres/version.go b/internal/postgres/version.go
index fdf8143..1a9c4c4 100644
--- a/internal/postgres/version.go
+++ b/internal/postgres/version.go
@@ -133,7 +133,7 @@
v1Path := internal.V1Path(fullPath, modulePath)
row = db.db.QueryRow(ctx, `SELECT path FROM units WHERE v1_path = $1 AND module_id = $2;`, v1Path, modID)
var path string
- switch row.Scan(&path) {
+ switch err := row.Scan(&path); err {
case nil:
return modPath, path, nil
case sql.ErrNoRows:
@@ -142,3 +142,36 @@
return "", "", err
}
}
+
+// GetLatestMinorModuleVersion returns the latest minor version of modulePath,
+// and whether unitPath exists at that version.
+func (db *DB) GetLatestMinorModuleVersion(ctx context.Context, unitPath, modulePath string) (version string, unitExists bool, err error) {
+ defer derrors.Wrap(&err, "DB.GetLatestMinorVersion(ctx, %q, %q)", unitPath, modulePath)
+
+ // Find the latest version of the module path.
+ var modID int
+ q, args, err := orderByLatest(squirrel.Select("m.version", "m.id").
+ From("modules m").
+ Where(squirrel.Eq{"m.module_path": modulePath})).
+ Limit(1).
+ ToSql()
+ if err != nil {
+ return "", false, err
+ }
+ row := db.db.QueryRow(ctx, q, args...)
+ if err := row.Scan(&version, &modID); err != nil {
+ return "", false, err
+ }
+
+ // See if the unit path exists at that version.
+ var x int
+ err = db.db.QueryRow(ctx, `SELECT 1 FROM units WHERE path = $1 AND module_id = $2`, unitPath, modID).Scan(&x)
+ switch err {
+ case nil:
+ return version, true, nil
+ case sql.ErrNoRows:
+ return version, false, nil
+ default:
+ return "", false, err
+ }
+}
diff --git a/internal/postgres/version_test.go b/internal/postgres/version_test.go
index 9e22452..d4713a5 100644
--- a/internal/postgres/version_test.go
+++ b/internal/postgres/version_test.go
@@ -298,3 +298,43 @@
}
}
}
+
+func TestGetLatestMinorModuleVersion(t *testing.T) {
+ ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
+ defer cancel()
+ defer ResetTestDB(testDB, t)
+
+ const (
+ modulePath = "foo.com/M"
+ latestVersion = "v1.2.0"
+ )
+
+ for _, m := range []*internal.Module{
+ sample.Module(modulePath, "v1.1.0", "p1", "p2"),
+ sample.Module(modulePath, latestVersion, "p1"),
+ sample.Module(modulePath+"/v2", "v2.0.5", "p1", "p2"),
+ } {
+ if err := testDB.InsertModule(ctx, m); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ for _, test := range []struct {
+ unitSuffix string
+ wantPresent bool
+ }{
+ {"p1", true},
+ {"p2", false},
+ } {
+ gotVersion, gotPresent, err := testDB.GetLatestMinorModuleVersion(ctx, modulePath+"/"+test.unitSuffix, modulePath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if gotVersion != latestVersion {
+ t.Errorf("%s: got version %q, want %q", test.unitSuffix, gotVersion, latestVersion)
+ }
+ if gotPresent != test.wantPresent {
+ t.Errorf("%s: got present %t, want %t", test.unitSuffix, gotPresent, test.wantPresent)
+ }
+ }
+}