Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
113804: sql: add `crdb_internal.release_series` builtin r=RaduBerinde a=RaduBerinde

This commit adds a built-in that resolves dev versions (e.g. 23.2-10)
to the corresponding release series (e.g. 24.1). This allows us to
clean up some tests and make them stable - they will no longer need to
be adjusted when minting a release.

Informs: cockroachdb#112629
Release note: None


Co-authored-by: Radu Berinde <[email protected]>
  • Loading branch information
craig[bot] and RaduBerinde committed Nov 7, 2023
2 parents 06eb79a + 15f92e5 commit 414cb46
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 64 deletions.
2 changes: 1 addition & 1 deletion pkg/ccl/logictestccl/testdata/logic_test/crdb_internal
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ ALTER TENANT [5] GRANT CAPABILITY can_admin_split
query ITT colnames,retry,rowsort
SELECT * FROM crdb_internal.node_tenant_capabilities_cache WHERE capability_name = 'can_admin_split'
----
tenant_id capability_name capability_value
tenant_id capability_name capability_value
1 can_admin_split true
5 can_admin_split true

Expand Down
8 changes: 4 additions & 4 deletions pkg/ccl/logictestccl/testdata/logic_test/crdb_internal_tenant
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,9 @@ select crdb_internal.get_vmodule()
·

query T
select regexp_replace(regexp_replace(crdb_internal.node_executable_version()::string, '(-\d+)?$', ''), '10000', '');
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
23.2
24.1

query ITTT colnames,rowsort
select node_id, component, field, regexp_replace(regexp_replace(value, '^\d+$', '<port>'), e':\\d+', ':<port>') as value from crdb_internal.node_runtime_info
Expand Down Expand Up @@ -488,9 +488,9 @@ select * from crdb_internal.gossip_alerts

# Anyone can see the executable version.
query T
select regexp_replace(regexp_replace(crdb_internal.node_executable_version()::string, '(-\d+)?$', ''), '10000', '');
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
23.2
24.1

user root

Expand Down
2 changes: 2 additions & 0 deletions pkg/clusterversion/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ go_library(
importpath = "github.com/cockroachdb/cockroach/pkg/clusterversion",
visibility = ["//visibility:public"],
deps = [
"//pkg/build",
"//pkg/roachpb",
"//pkg/settings",
"//pkg/util/envutil",
Expand All @@ -39,6 +40,7 @@ go_test(
args = ["-test.timeout=55s"],
embed = [":clusterversion"],
deps = [
"//pkg/build",
"//pkg/roachpb",
"//pkg/settings",
"//pkg/settings/cluster",
Expand Down
50 changes: 32 additions & 18 deletions pkg/clusterversion/cockroach_versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

package clusterversion

import "github.com/cockroachdb/cockroach/pkg/roachpb"
import (
"github.com/cockroachdb/cockroach/pkg/build"
"github.com/cockroachdb/cockroach/pkg/roachpb"
)

// Key is a unique identifier for a version of CockroachDB.
type Key int
Expand Down Expand Up @@ -650,34 +653,45 @@ const developmentBranch = true

// finalVersion should be set on a release branch to the minted final cluster
// version key, e.g. to V23_2 on the release-23.2 branch once it is minted.
// Setting it has the effect of ensuring no versions are subsequently added.
// Setting it has the effect of ensuring no versions are subsequently added (see
// TestFinalVersion).
const finalVersion Key = -1

func init() {
if finalVersion >= 0 {
if Latest != finalVersion {
panic("latest version does not match final version")
}
if developmentBranch {
panic("final version set on development branch")
}
} else if Latest.IsFinal() {
panic("finalVersion not set but latetest version is final")
}
}

// Version returns the roachpb.Version corresponding to a key.
func (k Key) Version() roachpb.Version {
version := versionTable[k]
return maybeDevOffset(k, version)
return maybeApplyDevOffset(k, version)
}

// IsFinal returns true if the key is a final version (as opposed to a
// transitional internal version during upgrade).
// IsFinal returns true if the key corresponds to a final version (as opposed to
// a transitional internal version during upgrade).
func (k Key) IsFinal() bool {
return k.Version().IsFinal()
}

// ReleaseSeries returns the final version for the release series the Key
// belongs to. Specifically:
// - if the key corresponds to a final version (e.g. 23.2), the result is the
// same version; e.g. V23_2.ReleaseSeries() is v23.2.
// - if the key corresponds to a transitional upgrade version (e.g. v23.2-8),
// the result is the next final version (e.g. v24.1).
//
// Note that the result does not have any DevOffset applied.
func (k Key) ReleaseSeries() roachpb.Version {
// Find the first key >= k that is a final version.
for k := k; k < numKeys; k++ {
if k.IsFinal() {
return removeDevOffset(k.Version())
}
}
// k is a dev version in the latest release series.
major, minor := build.BranchReleaseSeries()
return roachpb.Version{
Major: int32(major),
Minor: int32(minor),
}
}

func (k Key) String() string {
return k.Version().String()
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/clusterversion/cockroach_versions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
package clusterversion

import (
"fmt"
"testing"

"github.com/cockroachdb/cockroach/pkg/build"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
"github.com/cockroachdb/redact"
Expand Down Expand Up @@ -92,6 +94,15 @@ func TestKeyConstants(t *testing.T) {
require.Equal(t, PreviousRelease, supported[len(supported)-1])
}

func TestFinalVersion(t *testing.T) {
if finalVersion >= 0 {
require.False(t, developmentBranch, "final version set but developmentBranch is still set")
require.Equal(t, Latest, finalVersion, "finalVersion must match the minted latest version")
} else {
require.False(t, Latest.IsFinal(), "finalVersion not set but Latest is final")
}
}

func TestVersionFormat(t *testing.T) {
defer leaktest.AfterTest(t)()

Expand Down Expand Up @@ -147,3 +158,15 @@ func TestClusterVersionPrettyPrint(t *testing.T) {
}
}
}

func TestReleaseSeries(t *testing.T) {
require.Equal(t, fmt.Sprintf("v%s", Latest.ReleaseSeries()), build.BinaryVersionPrefix())
if Latest.IsFinal() {
require.True(t, Latest.Version() == Latest.ReleaseSeries())
} else {
require.True(t, removeDevOffset(Latest.Version()).Less(Latest.ReleaseSeries()))
}
require.Equal(t, PreviousRelease.ReleaseSeries(), removeDevOffset(PreviousRelease.Version()))
require.Equal(t, (PreviousRelease - 1).ReleaseSeries(), removeDevOffset(PreviousRelease.Version()))
require.Equal(t, MinSupported.ReleaseSeries(), removeDevOffset(MinSupported.Version()))
}
12 changes: 10 additions & 2 deletions pkg/clusterversion/dev_offset.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,18 @@ var devOffsetKeyStart = func() Key {
// a dev branch.
const DevOffset = 1_000_000

// maybeDevOffset applies DevOffset to the major version, if appropriate.
func maybeDevOffset(key Key, v roachpb.Version) roachpb.Version {
// maybeApplyDevOffset applies DevOffset to the major version, if appropriate.
func maybeApplyDevOffset(key Key, v roachpb.Version) roachpb.Version {
if key >= devOffsetKeyStart {
v.Major += DevOffset
}
return v
}

// removeDevOffset removes DevOffset from the given version, if it was applied.
func removeDevOffset(v roachpb.Version) roachpb.Version {
if v.Major > DevOffset {
v.Major -= DevOffset
}
return v
}
6 changes: 4 additions & 2 deletions pkg/roachpb/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ func (v Version) SafeFormat(p redact.SafePrinter, _ rune) {
p.Printf("%d.%d-%d", v.Major, v.Minor, v.Internal)
}

// IsFinal returns true if this is a final version (as opposed to a
// transitional internal version during upgrade).
// IsFinal returns true if this is a final version (as opposed to a transitional
// internal version during upgrade).
//
// A version is final iff Internal = 0.
func (v Version) IsFinal() bool {
return v.Internal == 0
}
Expand Down
14 changes: 10 additions & 4 deletions pkg/sql/logictest/testdata/logic_test/crdb_internal
Original file line number Diff line number Diff line change
Expand Up @@ -638,9 +638,15 @@ select crdb_internal.get_vmodule()
·

query T
select regexp_replace(crdb_internal.node_executable_version()::string, '(-\d+)?$', '');
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
1000023.2
24.1

query error version '1.0' not supported
SELECT crdb_internal.release_series('1.0')

query error version '2000000.0' not supported
SELECT crdb_internal.release_series('2000000.0')

query ITTT colnames,rowsort
select node_id, component, field, regexp_replace(regexp_replace(value, '^\d+$', '<port>'), e':\\d+', ':<port>') as value from crdb_internal.node_runtime_info
Expand Down Expand Up @@ -792,9 +798,9 @@ SELECT * FROM crdb_internal.check_consistency(true, b'\x02', b'\x04')

# Anyone can see the executable version.
query T
select regexp_replace(crdb_internal.node_executable_version()::string, '(-\d+)?$', '');
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
1000023.2
24.1

user root

Expand Down
24 changes: 12 additions & 12 deletions pkg/sql/logictest/testdata/logic_test/mixed_version_can_login
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ upgrade 0

upgrade 1

query B nodeidx=0
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T nodeidx=0
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

query T nodeidx=2
SELECT crdb_internal.node_executable_version()
Expand All @@ -22,18 +22,18 @@ SELECT crdb_internal.node_executable_version()
# Verify that a non-root user can login on the upgraded node.
user testuser nodeidx=0

query B
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

# Verify that a root user can login on the upgraded node.
user root nodeidx=1

query B
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

# Verify that a non-root user can login on the non-upgraded node.
user testuser nodeidx=2
Expand All @@ -53,7 +53,7 @@ SELECT crdb_internal.node_executable_version()

upgrade 2

query B
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ upgrade 1

# Test that there are no problems creating role memberships on a mixed-version cluster.

query B nodeidx=1
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T nodeidx=1
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

user root nodeidx=1

Expand Down Expand Up @@ -89,17 +89,17 @@ upgrade 2

# Verify that all nodes are now running 23.2 binaries.

query B nodeidx=0
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T nodeidx=0
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

query B nodeidx=1
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T nodeidx=1
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

query B nodeidx=2
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T nodeidx=2
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,20 @@ upgrade 2

# Verify that all nodes are now running 24.1 binaries.

query B nodeidx=0
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T nodeidx=0
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

query B nodeidx=1
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T nodeidx=1
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

query B nodeidx=2
SELECT crdb_internal.node_executable_version() SIMILAR TO '23.2-%'
query T nodeidx=2
SELECT crdb_internal.release_series(crdb_internal.node_executable_version())
----
true
24.1

# Makes sure the upgrade job has finished, and the cluster version gate is
# passed.
Expand Down
31 changes: 31 additions & 0 deletions pkg/sql/sem/builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -4995,6 +4995,37 @@ value if you rely on the HLC for accuracy.`,
},
),

"crdb_internal.release_series": makeBuiltin(
tree.FunctionProperties{Category: builtinconstants.CategorySystemInfo},
tree.Overload{
Types: tree.ParamTypes{{Name: "version", Typ: types.String}},
ReturnType: tree.FixedReturnType(types.String),
Fn: func(ctx context.Context, evalCtx *eval.Context, args tree.Datums) (tree.Datum, error) {
s, ok := tree.AsDString(args[0])
if !ok {
return nil, errors.Newf("expected string value, got %T", args[0])
}
version, err := roachpb.ParseVersion(string(s))
if err != nil {
return nil, err
}
if version.Less(clusterversion.MinSupported.Version()) || clusterversion.Latest.Version().Less(version) {
return nil, errors.Newf(
"version %s not supported; this binary only understands versions %s through %s",
args[0], clusterversion.MinSupported, clusterversion.Latest,
)
}
for k := clusterversion.Latest; ; k-- {
if k.Version().LessEq(version) {
return tree.NewDString(k.ReleaseSeries().String()), nil
}
}
},
Info: "Converts a cluster version to the final cluster version in that release series.",
Volatility: volatility.Stable,
},
),

"crdb_internal.approximate_timestamp": makeBuiltin(
tree.FunctionProperties{Category: builtinconstants.CategorySystemInfo},
tree.Overload{
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/sem/builtins/fixed_oids.go
Original file line number Diff line number Diff line change
Expand Up @@ -2510,6 +2510,7 @@ var builtinOidsArray = []string{
2539: `pg_encoding_max_length(encoding: int) -> int`,
2540: `information_schema._pg_datetime_precision(typid: oid, typmod: int4) -> int`,
2541: `information_schema._pg_interval_type(typid: oid, typmod: int4) -> string`,
2542: `crdb_internal.release_series(version: string) -> string`,
}

var builtinOidsBySignature map[string]oid.Oid
Expand Down
Loading

0 comments on commit 414cb46

Please sign in to comment.