-
Notifications
You must be signed in to change notification settings - Fork 245
/
version.go
81 lines (66 loc) · 2.11 KB
/
version.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package crdb
import (
"context"
"errors"
"fmt"
"regexp"
"strconv"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"github.com/rs/zerolog"
pgxcommon "github.com/authzed/spicedb/internal/datastore/postgres/common"
)
const (
queryVersionJSON = "SELECT crdb_internal.active_version()::jsonb;"
queryVersion = "SELECT version();"
errFunctionDoesNotExist = "42883"
)
var versionRegex = regexp.MustCompile(`v([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?`)
func queryServerVersion(ctx context.Context, db pgxcommon.DBFuncQuerier, version *crdbVersion) error {
if err := db.QueryRowFunc(ctx, func(ctx context.Context, row pgx.Row) error {
return row.Scan(version)
}, queryVersionJSON); err != nil {
var pgerr *pgconn.PgError
if !errors.As(err, &pgerr) || pgerr.Code != errFunctionDoesNotExist {
return err
}
// The crdb_internal.active_version() wasn't added until v22.1.X, try to parse the version
var versionStr string
if err := db.QueryRowFunc(ctx, func(ctx context.Context, row pgx.Row) error {
return row.Scan(&versionStr)
}, queryVersion); err != nil {
return err
}
return parseVersionStringInto(versionStr, version)
}
return nil
}
func parseVersionStringInto(versionStr string, version *crdbVersion) error {
found := versionRegex.FindStringSubmatch(versionStr)
if found == nil {
return fmt.Errorf("could not parse version from string: %s", versionStr)
}
var err error
version.Major, err = strconv.Atoi(found[1])
if err != nil {
return fmt.Errorf("invalid major version: %s", found[1])
}
version.Minor, err = strconv.Atoi(found[2])
if err != nil {
return fmt.Errorf("invalid minor version: %s", found[2])
}
version.Patch, err = strconv.Atoi(found[3])
if err != nil {
return fmt.Errorf("invalid patch version: %s", found[3])
}
return nil
}
type crdbVersion struct {
Internal int `json:"internal"`
Major int `json:"major"`
Minor int `json:"minor"`
Patch int `json:"patch"`
}
func (v crdbVersion) MarshalZerologObject(e *zerolog.Event) {
e.Int("major", v.Major).Int("minor", v.Minor).Int("patch", v.Patch)
}