diff --git a/docs/generated/http/full.md b/docs/generated/http/full.md index 2fb9bb9ff7db..ec72a8deb2a0 100644 --- a/docs/generated/http/full.md +++ b/docs/generated/http/full.md @@ -1431,7 +1431,9 @@ information about the resources on a node used by that table. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| node_id | [string](#cockroach.server.serverpb.HotRangesRequest-string) | | If left empty, hot ranges for all nodes/stores will be returned. | +| node_id | [string](#cockroach.server.serverpb.HotRangesRequest-string) | | NodeID indicates which node to query for a hot range report. It is posssible to populate any node ID; if the node receiving the request is not the target node, it will forward the request to the target node. + +If left empty, the request is forwarded to every node in the cluster. | @@ -1446,8 +1448,8 @@ information about the resources on a node used by that table. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| node_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | NodeID is the node that submitted all the requests. | -| hot_ranges_by_node_id | [HotRangesResponse.HotRangesByNodeIdEntry](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.HotRangesByNodeIdEntry) | repeated | | +| node_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | NodeID is the node that received the HotRangesRequest and forwarded requests to the selected target node(s). | +| hot_ranges_by_node_id | [HotRangesResponse.HotRangesByNodeIdEntry](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.HotRangesByNodeIdEntry) | repeated | HotRangesByNodeID contains a hot range report for each selected target node ID in the HotRangesRequest. | @@ -1471,8 +1473,10 @@ information about the resources on a node used by that table. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| error_message | [string](#cockroach.server.serverpb.HotRangesResponse-string) | | | -| stores | [HotRangesResponse.StoreResponse](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.StoreResponse) | repeated | | +| error_message | [string](#cockroach.server.serverpb.HotRangesResponse-string) | | ErrorMessage is set to a non-empty string if this target node was unable to produce a hot range report. + +The contents of this string indicates the cause of the failure. | +| stores | [HotRangesResponse.StoreResponse](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.StoreResponse) | repeated | Stores contains the hot ranges report if no error was encountered. There is one part to the report for each store in the target node. | @@ -1483,8 +1487,8 @@ information about the resources on a node used by that table. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| store_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | | -| hot_ranges | [HotRangesResponse.HotRange](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.HotRange) | repeated | | +| store_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | StoreID identifies the store for which the report was produced. | +| hot_ranges | [HotRangesResponse.HotRange](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.HotRange) | repeated | HotRanges is the hot ranges report for this store on the target node. | @@ -1495,8 +1499,10 @@ information about the resources on a node used by that table. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| desc | [cockroach.roachpb.RangeDescriptor](#cockroach.server.serverpb.HotRangesResponse-cockroach.roachpb.RangeDescriptor) | | | -| queries_per_second | [double](#cockroach.server.serverpb.HotRangesResponse-double) | | | +| desc | [cockroach.roachpb.RangeDescriptor](#cockroach.server.serverpb.HotRangesResponse-cockroach.roachpb.RangeDescriptor) | | Desc is the descriptor of the range for which the report was produced. + +Note: this field is generally RESERVED and will likely be removed or replaced in a later version. See: https://github.com/cockroachdb/cockroach/issues/53212 | +| queries_per_second | [double](#cockroach.server.serverpb.HotRangesResponse-double) | | QueriesPerSecond is the recent number of queries per second on this range. | diff --git a/docs/generated/http/hotranges.md b/docs/generated/http/hotranges.md index 77a609489733..b9680d7cc005 100644 --- a/docs/generated/http/hotranges.md +++ b/docs/generated/http/hotranges.md @@ -7,7 +7,9 @@ | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| node_id | [string](#cockroach.server.serverpb.HotRangesRequest-string) | | If left empty, hot ranges for all nodes/stores will be returned. | +| node_id | [string](#cockroach.server.serverpb.HotRangesRequest-string) | | NodeID indicates which node to query for a hot range report. It is posssible to populate any node ID; if the node receiving the request is not the target node, it will forward the request to the target node. + +If left empty, the request is forwarded to every node in the cluster. | @@ -22,8 +24,8 @@ | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| node_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | NodeID is the node that submitted all the requests. | -| hot_ranges_by_node_id | [HotRangesResponse.HotRangesByNodeIdEntry](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.HotRangesByNodeIdEntry) | repeated | | +| node_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | NodeID is the node that received the HotRangesRequest and forwarded requests to the selected target node(s). | +| hot_ranges_by_node_id | [HotRangesResponse.HotRangesByNodeIdEntry](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.HotRangesByNodeIdEntry) | repeated | HotRangesByNodeID contains a hot range report for each selected target node ID in the HotRangesRequest. | @@ -47,8 +49,10 @@ | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| error_message | [string](#cockroach.server.serverpb.HotRangesResponse-string) | | | -| stores | [HotRangesResponse.StoreResponse](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.StoreResponse) | repeated | | +| error_message | [string](#cockroach.server.serverpb.HotRangesResponse-string) | | ErrorMessage is set to a non-empty string if this target node was unable to produce a hot range report. + +The contents of this string indicates the cause of the failure. | +| stores | [HotRangesResponse.StoreResponse](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.StoreResponse) | repeated | Stores contains the hot ranges report if no error was encountered. There is one part to the report for each store in the target node. | @@ -59,8 +63,8 @@ | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| store_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | | -| hot_ranges | [HotRangesResponse.HotRange](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.HotRange) | repeated | | +| store_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | StoreID identifies the store for which the report was produced. | +| hot_ranges | [HotRangesResponse.HotRange](#cockroach.server.serverpb.HotRangesResponse-cockroach.server.serverpb.HotRangesResponse.HotRange) | repeated | HotRanges is the hot ranges report for this store on the target node. | @@ -71,8 +75,10 @@ | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| desc | [cockroach.roachpb.RangeDescriptor](#cockroach.server.serverpb.HotRangesResponse-cockroach.roachpb.RangeDescriptor) | | | -| queries_per_second | [double](#cockroach.server.serverpb.HotRangesResponse-double) | | | +| desc | [cockroach.roachpb.RangeDescriptor](#cockroach.server.serverpb.HotRangesResponse-cockroach.roachpb.RangeDescriptor) | | Desc is the descriptor of the range for which the report was produced. + +Note: this field is generally RESERVED and will likely be removed or replaced in a later version. See: https://github.com/cockroachdb/cockroach/issues/53212 | +| queries_per_second | [double](#cockroach.server.serverpb.HotRangesResponse-double) | | QueriesPerSecond is the recent number of queries per second on this range. | diff --git a/docs/generated/sql/aggregates.md b/docs/generated/sql/aggregates.md index 76c25dbcf759..3d3da7dd612f 100644 --- a/docs/generated/sql/aggregates.md +++ b/docs/generated/sql/aggregates.md @@ -195,6 +195,8 @@ st_makeline(arg1: geometry) → geometry

Forms a LineString from Point, MultiPoint or LineStrings. Other shapes will be ignored.

+st_union(arg1: geometry) → geometry

Applies a spatial union to the geometries provided.

+
stddev(arg1: decimal) → decimal

Calculates the standard deviation of the selected values.

stddev(arg1: float) → float

Calculates the standard deviation of the selected values.

diff --git a/docs/generated/sql/functions.md b/docs/generated/sql/functions.md index cc74673caf85..dbf2904548bf 100644 --- a/docs/generated/sql/functions.md +++ b/docs/generated/sql/functions.md @@ -974,6 +974,10 @@ has no relationship with the commit order of concurrent transactions.

st_azimuth(geometry_a: geometry, geometry_b: geometry) → float

Returns the azimuth in radians of the segment defined by the given point geometries, or NULL if the two points are coincident.

The azimuth is angle is referenced from north, and is positive clockwise: North = 0; East = π/2; South = π; West = 3π/2.

+st_box2dfromgeohash(geohash: string) → box2d

Return a Box2D from a GeoHash string with max precision.

+
+st_box2dfromgeohash(geohash: string, precision: int) → box2d

Return a Box2D from a GeoHash string with supplied precision.

+
st_buffer(geography: geography, distance: float) → geography

Returns a Geometry that represents all points whose distance is less than or equal to the given distance from the given Geometry.

This function utilizes the GEOS module.

@@ -1264,6 +1268,10 @@ Bottom Left.

st_geomfromewkt(val: string) → geometry

Returns the Geometry from an EWKT representation.

+st_geomfromgeohash(geohash: string) → geometry

Return a POLYGON Geometry from a GeoHash string with max precision.

+
+st_geomfromgeohash(geohash: string, precision: int) → geometry

Return a POLYGON Geometry from a GeoHash string with supplied precision.

+
st_geomfromgeojson(val: string) → geometry

Returns the Geometry from an GeoJSON representation.

st_geomfromgeojson(val: jsonb) → geometry

Returns the Geometry from an GeoJSON representation.

@@ -1486,9 +1494,9 @@ calculated, the result is transformed back into a Geography with SRID 4326.

st_point(x: float, y: float) → geometry

Returns a new Point with the given X and Y coordinates.

-st_pointfromgeohash(geohash: string) → geometry

Return a Geometry point from a GeoHash string with max precision.

+st_pointfromgeohash(geohash: string) → geometry

Return a POINT Geometry from a GeoHash string with max precision.

-st_pointfromgeohash(geohash: string, precision: int) → geometry

Return a Geometry point from a GeoHash string with supplied precision.

+st_pointfromgeohash(geohash: string, precision: int) → geometry

Return a POINT Geometry from a GeoHash string with supplied precision.

st_pointfromtext(str: string, srid: int) → geometry

Returns the Geometry from a WKT or EWKT representation with an SRID. If the shape underneath is not Point, NULL is returned. If the SRID is present in both the EWKT and the argument, the argument value is used.

@@ -1601,9 +1609,6 @@ Negative azimuth values and values greater than 2π (360 degrees) are supported.
st_translate(g: geometry, deltaX: float, deltaY: float) → geometry

Returns a modified Geometry translated by the given deltas

-st_union(geometry_a: geometry, geometry_b: geometry) → geometry

Returns the union of the given geometries as a single Geometry object.

-

This function utilizes the GEOS module.

-
st_within(geometry_a: geometry, geometry_b: geometry) → bool

Returns true if geometry_a is completely inside geometry_b.

This function utilizes the GEOS module.

This function variant will attempt to utilize any available geospatial index.

diff --git a/pkg/geo/geohash.go b/pkg/geo/geohash.go deleted file mode 100644 index 3b028129874f..000000000000 --- a/pkg/geo/geohash.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -package geo - -import ( - "github.com/cockroachdb/errors" - "github.com/pierrre/geohash" -) - -// NewGeometryPointFromGeoHash converts a GeoHash to a Geometry Point -// using a Lng/Lat Point representation of the GeoHash. -func NewGeometryPointFromGeoHash(g string, precision int) (*Geometry, error) { - if len(g) == 0 { - return nil, errors.Newf("Length of geohash must be greater than 0") - } - - // If precision is more than the length of the geohash - // or if precision is less than 0 then set - // precision equal to length of geohash. - if precision > len(g) || precision < 0 { - precision = len(g) - } - box, err := geohash.Decode(g[0:precision]) - if err != nil { - return nil, err - } - point := box.Round() - geom, gErr := NewGeometryFromPointCoords(point.Lon, point.Lat) - if gErr != nil { - return nil, gErr - } - return geom, nil -} diff --git a/pkg/geo/parse.go b/pkg/geo/parse.go index 9092e8dd5500..96fbd8548d8f 100644 --- a/pkg/geo/parse.go +++ b/pkg/geo/parse.go @@ -18,6 +18,8 @@ import ( "github.com/cockroachdb/cockroach/pkg/geo/geopb" "github.com/cockroachdb/cockroach/pkg/geo/geos" "github.com/cockroachdb/cockroach/pkg/util" + "github.com/cockroachdb/errors" + "github.com/pierrre/geohash" "github.com/twpayne/go-geom" "github.com/twpayne/go-geom/encoding/ewkb" "github.com/twpayne/go-geom/encoding/ewkbhex" @@ -209,3 +211,52 @@ func hasPrefixIgnoreCase(str string, prefix string) bool { } return true } + +// ParseGeometryPointFromGeoHash converts a GeoHash to a Geometry Point +// using a Lng/Lat Point representation of the GeoHash. +func ParseGeometryPointFromGeoHash(g string, precision int) (*Geometry, error) { + box, err := parseGeoHash(g, precision) + if err != nil { + return nil, err + } + point := box.Center() + geom, gErr := NewGeometryFromPointCoords(point.Lon, point.Lat) + if gErr != nil { + return nil, gErr + } + return geom, nil +} + +// ParseCartesianBoundingBoxFromGeoHash converts a GeoHash to a CartesianBoundingBox. +func ParseCartesianBoundingBoxFromGeoHash(g string, precision int) (CartesianBoundingBox, error) { + box, err := parseGeoHash(g, precision) + if err != nil { + return CartesianBoundingBox{}, err + } + return CartesianBoundingBox{ + BoundingBox: geopb.BoundingBox{ + LoX: box.Lon.Min, + HiX: box.Lon.Max, + LoY: box.Lat.Min, + HiY: box.Lat.Max, + }, + }, nil +} + +func parseGeoHash(g string, precision int) (geohash.Box, error) { + if len(g) == 0 { + return geohash.Box{}, errors.Newf("length of GeoHash must be greater than 0") + } + + // If precision is more than the length of the geohash + // or if precision is less than 0 then set + // precision equal to length of geohash. + if precision > len(g) || precision < 0 { + precision = len(g) + } + box, err := geohash.Decode(g[:precision]) + if err != nil { + return geohash.Box{}, err + } + return box, nil +} diff --git a/pkg/geo/parse_test.go b/pkg/geo/parse_test.go index 474d472114ab..2cdddf871799 100644 --- a/pkg/geo/parse_test.go +++ b/pkg/geo/parse_test.go @@ -11,9 +11,11 @@ package geo import ( + "fmt" "testing" "github.com/cockroachdb/cockroach/pkg/geo/geopb" + "github.com/pierrre/geohash" "github.com/stretchr/testify/require" ) @@ -589,3 +591,83 @@ func TestParseGeography(t *testing.T) { }) } } + +func TestParseHash(t *testing.T) { + testCases := []struct { + h string + p int + expected geohash.Box + }{ + {"123", 2, geohash.Box{ + Lat: geohash.Range{ + Min: -90, + Max: -84.375, + }, + Lon: geohash.Range{ + Min: -123.75, + Max: -112.5, + }, + }}, + {"123", 3, geohash.Box{ + Lat: geohash.Range{ + Min: -88.59375, + Max: -87.1875, + }, + Lon: geohash.Range{ + Min: -122.34375, + Max: -120.9375, + }, + }}, + {"123", 4, geohash.Box{ + Lat: geohash.Range{ + Min: -88.59375, + Max: -87.1875, + }, + Lon: geohash.Range{ + Min: -122.34375, + Max: -120.9375, + }, + }}, + {"123", -1, geohash.Box{ + Lat: geohash.Range{ + Min: -88.59375, + Max: -87.1875, + }, + Lon: geohash.Range{ + Min: -122.34375, + Max: -120.9375, + }, + }}, + } + for _, tc := range testCases { + t.Run(fmt.Sprintf("%s[:%d]", tc.h, tc.p), func(t *testing.T) { + ret, err := parseGeoHash(tc.h, tc.p) + require.NoError(t, err) + require.Equal(t, tc.expected, ret) + }) + } + + errorCases := []struct { + h string + p int + err string + }{ + { + "", + 10, + "length of GeoHash must be greater than 0", + }, + { + "-", + 10, + `geohash decode '-': invalid character at index 0`, + }, + } + for _, tc := range errorCases { + t.Run(fmt.Sprintf("%s[:%d]", tc.h, tc.p), func(t *testing.T) { + _, err := parseGeoHash(tc.h, tc.p) + require.Error(t, err) + require.EqualError(t, err, tc.err) + }) + } +} diff --git a/pkg/kv/kvclient/kvcoord/txn_interceptor_span_refresher.go b/pkg/kv/kvclient/kvcoord/txn_interceptor_span_refresher.go index c36fddc1195f..996c9b579734 100644 --- a/pkg/kv/kvclient/kvcoord/txn_interceptor_span_refresher.go +++ b/pkg/kv/kvclient/kvcoord/txn_interceptor_span_refresher.go @@ -271,7 +271,6 @@ func (sr *txnSpanRefresher) sendLockedWithRefreshAttempts( // chances that the refresh fails. bumpedTxn := br.Txn.Clone() bumpedTxn.WriteTooOld = false - bumpedTxn.ReadTimestamp = bumpedTxn.WriteTimestamp pErr = roachpb.NewErrorWithTxn( roachpb.NewTransactionRetryError(roachpb.RETRY_WRITE_TOO_OLD, "WriteTooOld flag converted to WriteTooOldError"), @@ -301,8 +300,7 @@ func (sr *txnSpanRefresher) maybeRefreshAndRetrySend( if !canRefreshTxn || !sr.canAutoRetry { return nil, pErr } - log.VEventf(ctx, 2, "retrying %s at refreshed timestamp %s because of %s", - ba, refreshTxn.ReadTimestamp, pErr) + log.VEventf(ctx, 2, "trying to refresh to %s because of %s", refreshTxn.ReadTimestamp, pErr) // Try updating the txn spans so we can retry. if ok := sr.tryUpdatingTxnSpans(ctx, refreshTxn); !ok { @@ -562,7 +560,9 @@ func (sr *txnSpanRefresher) appendRefreshSpans( } ba.RefreshSpanIterate(br, func(span roachpb.Span) { - log.VEventf(ctx, 3, "recording span to refresh: %s", span) + if log.ExpensiveLogEnabled(ctx, 3) { + log.VEventf(ctx, 3, "recording span to refresh: %s", span.String()) + } sr.refreshFootprint.insert(span) }) return nil diff --git a/pkg/kv/kvserver/client_tenant_test.go b/pkg/kv/kvserver/client_tenant_test.go index 8661c66a4de8..2ed7fd887d9e 100644 --- a/pkg/kv/kvserver/client_tenant_test.go +++ b/pkg/kv/kvserver/client_tenant_test.go @@ -33,7 +33,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/encoding" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/cockroachdb/cockroach/pkg/util/metric" - "github.com/cockroachdb/cockroach/pkg/util/quotapool" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/cockroach/pkg/util/uuid" "github.com/cockroachdb/errors" "github.com/stretchr/testify/require" @@ -144,7 +144,7 @@ func TestTenantRateLimiter(t *testing.T) { // This test utilizes manual time to make the rate-limiting calculations more // obvious. This timesource is not used inside the actual database. t0 := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) - timeSource := quotapool.NewManualTime(t0) + timeSource := timeutil.NewManualTime(t0) s, sqlDB, db := serverutils.StartServer(t, base.TestServerArgs{ Knobs: base.TestingKnobs{ diff --git a/pkg/kv/kvserver/tenantrate/factory.go b/pkg/kv/kvserver/tenantrate/factory.go index a2a141941e55..cd075e64bfc6 100644 --- a/pkg/kv/kvserver/tenantrate/factory.go +++ b/pkg/kv/kvserver/tenantrate/factory.go @@ -15,12 +15,13 @@ import ( "github.com/cockroachdb/cockroach/pkg/settings/cluster" "github.com/cockroachdb/cockroach/pkg/util/quotapool" "github.com/cockroachdb/cockroach/pkg/util/syncutil" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/errors" ) // TestingKnobs configures a LimiterFactory for testing. type TestingKnobs struct { - TimeSource quotapool.TimeSource + TimeSource timeutil.TimeSource } // LimiterFactory constructs and manages per-tenant Limiters. diff --git a/pkg/kv/kvserver/tenantrate/limiter.go b/pkg/kv/kvserver/tenantrate/limiter.go index 4ca3405d80bc..0c5b96c158a1 100644 --- a/pkg/kv/kvserver/tenantrate/limiter.go +++ b/pkg/kv/kvserver/tenantrate/limiter.go @@ -17,6 +17,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/roachpb" "github.com/cockroachdb/cockroach/pkg/util/quotapool" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/errors" ) @@ -129,7 +130,7 @@ func (rl *limiter) updateLimits(limits LimitConfigs) { // tokenBuckets is the implementation of Resource which remains in the quotapool // for a limiter. type tokenBuckets struct { - clock quotapool.TimeSource + clock timeutil.TimeSource lastUpdated time.Time requests tokenBucket readBytes tokenBucket diff --git a/pkg/kv/kvserver/tenantrate/limiter_test.go b/pkg/kv/kvserver/tenantrate/limiter_test.go index 8091cf83a731..20648b4ab107 100644 --- a/pkg/kv/kvserver/tenantrate/limiter_test.go +++ b/pkg/kv/kvserver/tenantrate/limiter_test.go @@ -27,7 +27,6 @@ import ( "github.com/cockroachdb/cockroach/pkg/testutils" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/cockroachdb/cockroach/pkg/util/metric" - "github.com/cockroachdb/cockroach/pkg/util/quotapool" "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/datadriven" "github.com/cockroachdb/errors" @@ -40,7 +39,7 @@ func TestCloser(t *testing.T) { st := cluster.MakeTestingClusterSettings() start := timeutil.Now() - timeSource := quotapool.NewManualTime(start) + timeSource := timeutil.NewManualTime(start) factory := tenantrate.NewLimiterFactory(st, &tenantrate.TestingKnobs{ TimeSource: timeSource, }) @@ -76,7 +75,7 @@ type testState struct { running map[string]*launchState rl *tenantrate.LimiterFactory m *metric.Registry - clock *quotapool.ManualTime + clock *timeutil.ManualTime settings *cluster.Settings } @@ -140,7 +139,7 @@ func (ts *testState) init(t *testing.T, d *datadriven.TestData) string { ts.initialized = true ts.running = make(map[string]*launchState) ts.tenants = make(map[roachpb.TenantID][]tenantrate.Limiter) - ts.clock = quotapool.NewManualTime(t0) + ts.clock = timeutil.NewManualTime(t0) ts.settings = cluster.MakeTestingClusterSettings() limits := tenantrate.LimitConfigsFromSettings(ts.settings) parseLimits(t, d, &limits) diff --git a/pkg/roachpb/data.go b/pkg/roachpb/data.go index 3a3d8e200225..fac7d73d4e27 100644 --- a/pkg/roachpb/data.go +++ b/pkg/roachpb/data.go @@ -1414,7 +1414,7 @@ func PrepareTransactionForRetry( // the restart. case *WriteTooOldError: // Increase the timestamp to the ts at which we've actually written. - txn.WriteTimestamp.Forward(writeTooOldRetryTimestamp(&txn, tErr)) + txn.WriteTimestamp.Forward(writeTooOldRetryTimestamp(tErr)) default: log.Fatalf(ctx, "invalid retryable err (%T): %s", pErr.GetDetail(), pErr) } @@ -1430,7 +1430,7 @@ func PrepareTransactionForRetry( // PrepareTransactionForRefresh returns whether the transaction can be refreshed // to the specified timestamp to avoid a client-side transaction restart. If // true, returns a cloned, updated Transaction object with the provisional -// commit timestamp and refreshed timestamp set appropriately. +// commit timestamp and read timestamp set appropriately. func PrepareTransactionForRefresh(txn *Transaction, timestamp hlc.Timestamp) (bool, *Transaction) { if txn.CommitTimestampFixed { return false, nil @@ -1443,8 +1443,7 @@ func PrepareTransactionForRefresh(txn *Transaction, timestamp hlc.Timestamp) (bo // CanTransactionRefresh returns whether the transaction specified in the // supplied error can be retried at a refreshed timestamp to avoid a client-side // transaction restart. If true, returns a cloned, updated Transaction object -// with the provisional commit timestamp and refreshed timestamp set -// appropriately. +// with the provisional commit timestamp and read timestamp set appropriately. func CanTransactionRefresh(ctx context.Context, pErr *Error) (bool, *Transaction) { txn := pErr.GetTxn() if txn == nil { @@ -1462,7 +1461,7 @@ func CanTransactionRefresh(ctx context.Context, pErr *Error) (bool, *Transaction // error, obviously the refresh will fail. It might be worth trying to // detect these cases and save the futile attempt; we'd need to have access // to the key that generated the error. - timestamp.Forward(writeTooOldRetryTimestamp(txn, err)) + timestamp.Forward(writeTooOldRetryTimestamp(err)) case *ReadWithinUncertaintyIntervalError: timestamp.Forward( readWithinUncertaintyIntervalRetryTimestamp(ctx, txn, err, pErr.OriginNode)) @@ -1490,7 +1489,7 @@ func readWithinUncertaintyIntervalRetryTimestamp( return ts } -func writeTooOldRetryTimestamp(txn *Transaction, err *WriteTooOldError) hlc.Timestamp { +func writeTooOldRetryTimestamp(err *WriteTooOldError) hlc.Timestamp { return err.ActualTimestamp } diff --git a/pkg/server/serverpb/status.pb.go b/pkg/server/serverpb/status.pb.go index 82d0d5866f7d..ca36a0dd2540 100644 --- a/pkg/server/serverpb/status.pb.go +++ b/pkg/server/serverpb/status.pb.go @@ -65,7 +65,7 @@ func (x StacksType) String() string { return proto.EnumName(StacksType_name, int32(x)) } func (StacksType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{0} + return fileDescriptor_status_0225a3e6e509791f, []int{0} } // Represents the type of file. @@ -92,7 +92,7 @@ func (x FileType) String() string { return proto.EnumName(FileType_name, int32(x)) } func (FileType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{1} + return fileDescriptor_status_0225a3e6e509791f, []int{1} } // We use an enum to allow reporting of client certs and potential others (eg: @@ -129,7 +129,7 @@ func (x CertificateDetails_CertificateType) String() string { return proto.EnumName(CertificateDetails_CertificateType_name, int32(x)) } func (CertificateDetails_CertificateType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{1, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{1, 0} } type ProfileRequest_Type int32 @@ -152,7 +152,7 @@ func (x ProfileRequest_Type) String() string { return proto.EnumName(ProfileRequest_Type_name, int32(x)) } func (ProfileRequest_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{37, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{37, 0} } // Enum for phase of execution. @@ -176,7 +176,7 @@ func (x ActiveQuery_Phase) String() string { return proto.EnumName(ActiveQuery_Phase_name, int32(x)) } func (ActiveQuery_Phase) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{45, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{45, 0} } type CertificatesRequest struct { @@ -189,7 +189,7 @@ func (m *CertificatesRequest) Reset() { *m = CertificatesRequest{} } func (m *CertificatesRequest) String() string { return proto.CompactTextString(m) } func (*CertificatesRequest) ProtoMessage() {} func (*CertificatesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{0} + return fileDescriptor_status_0225a3e6e509791f, []int{0} } func (m *CertificatesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -228,7 +228,7 @@ func (m *CertificateDetails) Reset() { *m = CertificateDetails{} } func (m *CertificateDetails) String() string { return proto.CompactTextString(m) } func (*CertificateDetails) ProtoMessage() {} func (*CertificateDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{1} + return fileDescriptor_status_0225a3e6e509791f, []int{1} } func (m *CertificateDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -269,7 +269,7 @@ func (m *CertificateDetails_Fields) Reset() { *m = CertificateDetails_Fi func (m *CertificateDetails_Fields) String() string { return proto.CompactTextString(m) } func (*CertificateDetails_Fields) ProtoMessage() {} func (*CertificateDetails_Fields) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{1, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{1, 0} } func (m *CertificateDetails_Fields) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -302,7 +302,7 @@ func (m *CertificatesResponse) Reset() { *m = CertificatesResponse{} } func (m *CertificatesResponse) String() string { return proto.CompactTextString(m) } func (*CertificatesResponse) ProtoMessage() {} func (*CertificatesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{2} + return fileDescriptor_status_0225a3e6e509791f, []int{2} } func (m *CertificatesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -339,7 +339,7 @@ func (m *DetailsRequest) Reset() { *m = DetailsRequest{} } func (m *DetailsRequest) String() string { return proto.CompactTextString(m) } func (*DetailsRequest) ProtoMessage() {} func (*DetailsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{3} + return fileDescriptor_status_0225a3e6e509791f, []int{3} } func (m *DetailsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -376,7 +376,7 @@ func (m *SystemInfo) Reset() { *m = SystemInfo{} } func (m *SystemInfo) String() string { return proto.CompactTextString(m) } func (*SystemInfo) ProtoMessage() {} func (*SystemInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{4} + return fileDescriptor_status_0225a3e6e509791f, []int{4} } func (m *SystemInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -413,7 +413,7 @@ func (m *DetailsResponse) Reset() { *m = DetailsResponse{} } func (m *DetailsResponse) String() string { return proto.CompactTextString(m) } func (*DetailsResponse) ProtoMessage() {} func (*DetailsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{5} + return fileDescriptor_status_0225a3e6e509791f, []int{5} } func (m *DetailsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -445,7 +445,7 @@ func (m *NodesRequest) Reset() { *m = NodesRequest{} } func (m *NodesRequest) String() string { return proto.CompactTextString(m) } func (*NodesRequest) ProtoMessage() {} func (*NodesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{6} + return fileDescriptor_status_0225a3e6e509791f, []int{6} } func (m *NodesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -479,7 +479,7 @@ func (m *NodesResponse) Reset() { *m = NodesResponse{} } func (m *NodesResponse) String() string { return proto.CompactTextString(m) } func (*NodesResponse) ProtoMessage() {} func (*NodesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{7} + return fileDescriptor_status_0225a3e6e509791f, []int{7} } func (m *NodesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -514,7 +514,7 @@ func (m *NodeRequest) Reset() { *m = NodeRequest{} } func (m *NodeRequest) String() string { return proto.CompactTextString(m) } func (*NodeRequest) ProtoMessage() {} func (*NodeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{8} + return fileDescriptor_status_0225a3e6e509791f, []int{8} } func (m *NodeRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -559,7 +559,7 @@ func (m *RaftState) Reset() { *m = RaftState{} } func (m *RaftState) String() string { return proto.CompactTextString(m) } func (*RaftState) ProtoMessage() {} func (*RaftState) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{9} + return fileDescriptor_status_0225a3e6e509791f, []int{9} } func (m *RaftState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -596,7 +596,7 @@ func (m *RaftState_Progress) Reset() { *m = RaftState_Progress{} } func (m *RaftState_Progress) String() string { return proto.CompactTextString(m) } func (*RaftState_Progress) ProtoMessage() {} func (*RaftState_Progress) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{9, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{9, 0} } func (m *RaftState_Progress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -641,7 +641,7 @@ func (m *RangeProblems) Reset() { *m = RangeProblems{} } func (m *RangeProblems) String() string { return proto.CompactTextString(m) } func (*RangeProblems) ProtoMessage() {} func (*RangeProblems) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{10} + return fileDescriptor_status_0225a3e6e509791f, []int{10} } func (m *RangeProblems) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -677,7 +677,7 @@ func (m *RangeStatistics) Reset() { *m = RangeStatistics{} } func (m *RangeStatistics) String() string { return proto.CompactTextString(m) } func (*RangeStatistics) ProtoMessage() {} func (*RangeStatistics) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{11} + return fileDescriptor_status_0225a3e6e509791f, []int{11} } func (m *RangeStatistics) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -711,7 +711,7 @@ func (m *PrettySpan) Reset() { *m = PrettySpan{} } func (m *PrettySpan) String() string { return proto.CompactTextString(m) } func (*PrettySpan) ProtoMessage() {} func (*PrettySpan) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{12} + return fileDescriptor_status_0225a3e6e509791f, []int{12} } func (m *PrettySpan) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -757,7 +757,7 @@ func (m *RangeInfo) Reset() { *m = RangeInfo{} } func (m *RangeInfo) String() string { return proto.CompactTextString(m) } func (*RangeInfo) ProtoMessage() {} func (*RangeInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{13} + return fileDescriptor_status_0225a3e6e509791f, []int{13} } func (m *RangeInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -793,7 +793,7 @@ func (m *RangesRequest) Reset() { *m = RangesRequest{} } func (m *RangesRequest) String() string { return proto.CompactTextString(m) } func (*RangesRequest) ProtoMessage() {} func (*RangesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{14} + return fileDescriptor_status_0225a3e6e509791f, []int{14} } func (m *RangesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -826,7 +826,7 @@ func (m *RangesResponse) Reset() { *m = RangesResponse{} } func (m *RangesResponse) String() string { return proto.CompactTextString(m) } func (*RangesResponse) ProtoMessage() {} func (*RangesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{15} + return fileDescriptor_status_0225a3e6e509791f, []int{15} } func (m *RangesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -861,7 +861,7 @@ func (m *GossipRequest) Reset() { *m = GossipRequest{} } func (m *GossipRequest) String() string { return proto.CompactTextString(m) } func (*GossipRequest) ProtoMessage() {} func (*GossipRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{16} + return fileDescriptor_status_0225a3e6e509791f, []int{16} } func (m *GossipRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -896,7 +896,7 @@ func (m *EngineStatsInfo) Reset() { *m = EngineStatsInfo{} } func (m *EngineStatsInfo) String() string { return proto.CompactTextString(m) } func (*EngineStatsInfo) ProtoMessage() {} func (*EngineStatsInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{17} + return fileDescriptor_status_0225a3e6e509791f, []int{17} } func (m *EngineStatsInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -931,7 +931,7 @@ func (m *EngineStatsRequest) Reset() { *m = EngineStatsRequest{} } func (m *EngineStatsRequest) String() string { return proto.CompactTextString(m) } func (*EngineStatsRequest) ProtoMessage() {} func (*EngineStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{18} + return fileDescriptor_status_0225a3e6e509791f, []int{18} } func (m *EngineStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -964,7 +964,7 @@ func (m *EngineStatsResponse) Reset() { *m = EngineStatsResponse{} } func (m *EngineStatsResponse) String() string { return proto.CompactTextString(m) } func (*EngineStatsResponse) ProtoMessage() {} func (*EngineStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{19} + return fileDescriptor_status_0225a3e6e509791f, []int{19} } func (m *EngineStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -998,7 +998,7 @@ func (m *TraceEvent) Reset() { *m = TraceEvent{} } func (m *TraceEvent) String() string { return proto.CompactTextString(m) } func (*TraceEvent) ProtoMessage() {} func (*TraceEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{20} + return fileDescriptor_status_0225a3e6e509791f, []int{20} } func (m *TraceEvent) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1032,7 +1032,7 @@ func (m *AllocatorDryRun) Reset() { *m = AllocatorDryRun{} } func (m *AllocatorDryRun) String() string { return proto.CompactTextString(m) } func (*AllocatorDryRun) ProtoMessage() {} func (*AllocatorDryRun) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{21} + return fileDescriptor_status_0225a3e6e509791f, []int{21} } func (m *AllocatorDryRun) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1065,7 +1065,7 @@ func (m *AllocatorRangeRequest) Reset() { *m = AllocatorRangeRequest{} } func (m *AllocatorRangeRequest) String() string { return proto.CompactTextString(m) } func (*AllocatorRangeRequest) ProtoMessage() {} func (*AllocatorRangeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{22} + return fileDescriptor_status_0225a3e6e509791f, []int{22} } func (m *AllocatorRangeRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1101,7 +1101,7 @@ func (m *AllocatorRangeResponse) Reset() { *m = AllocatorRangeResponse{} func (m *AllocatorRangeResponse) String() string { return proto.CompactTextString(m) } func (*AllocatorRangeResponse) ProtoMessage() {} func (*AllocatorRangeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{23} + return fileDescriptor_status_0225a3e6e509791f, []int{23} } func (m *AllocatorRangeResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1135,7 +1135,7 @@ func (m *AllocatorRequest) Reset() { *m = AllocatorRequest{} } func (m *AllocatorRequest) String() string { return proto.CompactTextString(m) } func (*AllocatorRequest) ProtoMessage() {} func (*AllocatorRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{24} + return fileDescriptor_status_0225a3e6e509791f, []int{24} } func (m *AllocatorRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1168,7 +1168,7 @@ func (m *AllocatorResponse) Reset() { *m = AllocatorResponse{} } func (m *AllocatorResponse) String() string { return proto.CompactTextString(m) } func (*AllocatorResponse) ProtoMessage() {} func (*AllocatorResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{25} + return fileDescriptor_status_0225a3e6e509791f, []int{25} } func (m *AllocatorResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1201,7 +1201,7 @@ func (m *JSONResponse) Reset() { *m = JSONResponse{} } func (m *JSONResponse) String() string { return proto.CompactTextString(m) } func (*JSONResponse) ProtoMessage() {} func (*JSONResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{26} + return fileDescriptor_status_0225a3e6e509791f, []int{26} } func (m *JSONResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1237,7 +1237,7 @@ func (m *ResponseError) Reset() { *m = ResponseError{} } func (m *ResponseError) String() string { return proto.CompactTextString(m) } func (*ResponseError) ProtoMessage() {} func (*ResponseError) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{27} + return fileDescriptor_status_0225a3e6e509791f, []int{27} } func (m *ResponseError) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1289,7 +1289,7 @@ func (m *LogsRequest) Reset() { *m = LogsRequest{} } func (m *LogsRequest) String() string { return proto.CompactTextString(m) } func (*LogsRequest) ProtoMessage() {} func (*LogsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{28} + return fileDescriptor_status_0225a3e6e509791f, []int{28} } func (m *LogsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1322,7 +1322,7 @@ func (m *LogEntriesResponse) Reset() { *m = LogEntriesResponse{} } func (m *LogEntriesResponse) String() string { return proto.CompactTextString(m) } func (*LogEntriesResponse) ProtoMessage() {} func (*LogEntriesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{29} + return fileDescriptor_status_0225a3e6e509791f, []int{29} } func (m *LogEntriesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1357,7 +1357,7 @@ func (m *LogFilesListRequest) Reset() { *m = LogFilesListRequest{} } func (m *LogFilesListRequest) String() string { return proto.CompactTextString(m) } func (*LogFilesListRequest) ProtoMessage() {} func (*LogFilesListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{30} + return fileDescriptor_status_0225a3e6e509791f, []int{30} } func (m *LogFilesListRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1390,7 +1390,7 @@ func (m *LogFilesListResponse) Reset() { *m = LogFilesListResponse{} } func (m *LogFilesListResponse) String() string { return proto.CompactTextString(m) } func (*LogFilesListResponse) ProtoMessage() {} func (*LogFilesListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{31} + return fileDescriptor_status_0225a3e6e509791f, []int{31} } func (m *LogFilesListResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1438,7 +1438,7 @@ func (m *LogFileRequest) Reset() { *m = LogFileRequest{} } func (m *LogFileRequest) String() string { return proto.CompactTextString(m) } func (*LogFileRequest) ProtoMessage() {} func (*LogFileRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{32} + return fileDescriptor_status_0225a3e6e509791f, []int{32} } func (m *LogFileRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1474,7 +1474,7 @@ func (m *StacksRequest) Reset() { *m = StacksRequest{} } func (m *StacksRequest) String() string { return proto.CompactTextString(m) } func (*StacksRequest) ProtoMessage() {} func (*StacksRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{33} + return fileDescriptor_status_0225a3e6e509791f, []int{33} } func (m *StacksRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1510,7 +1510,7 @@ func (m *File) Reset() { *m = File{} } func (m *File) String() string { return proto.CompactTextString(m) } func (*File) ProtoMessage() {} func (*File) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{34} + return fileDescriptor_status_0225a3e6e509791f, []int{34} } func (m *File) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1554,7 +1554,7 @@ func (m *GetFilesRequest) Reset() { *m = GetFilesRequest{} } func (m *GetFilesRequest) String() string { return proto.CompactTextString(m) } func (*GetFilesRequest) ProtoMessage() {} func (*GetFilesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{35} + return fileDescriptor_status_0225a3e6e509791f, []int{35} } func (m *GetFilesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1587,7 +1587,7 @@ func (m *GetFilesResponse) Reset() { *m = GetFilesResponse{} } func (m *GetFilesResponse) String() string { return proto.CompactTextString(m) } func (*GetFilesResponse) ProtoMessage() {} func (*GetFilesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{36} + return fileDescriptor_status_0225a3e6e509791f, []int{36} } func (m *GetFilesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1625,7 +1625,7 @@ func (m *ProfileRequest) Reset() { *m = ProfileRequest{} } func (m *ProfileRequest) String() string { return proto.CompactTextString(m) } func (*ProfileRequest) ProtoMessage() {} func (*ProfileRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{37} + return fileDescriptor_status_0225a3e6e509791f, []int{37} } func (m *ProfileRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1660,7 +1660,7 @@ func (m *MetricsRequest) Reset() { *m = MetricsRequest{} } func (m *MetricsRequest) String() string { return proto.CompactTextString(m) } func (*MetricsRequest) ProtoMessage() {} func (*MetricsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{38} + return fileDescriptor_status_0225a3e6e509791f, []int{38} } func (m *MetricsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1694,7 +1694,7 @@ func (m *RaftRangeNode) Reset() { *m = RaftRangeNode{} } func (m *RaftRangeNode) String() string { return proto.CompactTextString(m) } func (*RaftRangeNode) ProtoMessage() {} func (*RaftRangeNode) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{39} + return fileDescriptor_status_0225a3e6e509791f, []int{39} } func (m *RaftRangeNode) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1727,7 +1727,7 @@ func (m *RaftRangeError) Reset() { *m = RaftRangeError{} } func (m *RaftRangeError) String() string { return proto.CompactTextString(m) } func (*RaftRangeError) ProtoMessage() {} func (*RaftRangeError) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{40} + return fileDescriptor_status_0225a3e6e509791f, []int{40} } func (m *RaftRangeError) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1762,7 +1762,7 @@ func (m *RaftRangeStatus) Reset() { *m = RaftRangeStatus{} } func (m *RaftRangeStatus) String() string { return proto.CompactTextString(m) } func (*RaftRangeStatus) ProtoMessage() {} func (*RaftRangeStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{41} + return fileDescriptor_status_0225a3e6e509791f, []int{41} } func (m *RaftRangeStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1795,7 +1795,7 @@ func (m *RaftDebugRequest) Reset() { *m = RaftDebugRequest{} } func (m *RaftDebugRequest) String() string { return proto.CompactTextString(m) } func (*RaftDebugRequest) ProtoMessage() {} func (*RaftDebugRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{42} + return fileDescriptor_status_0225a3e6e509791f, []int{42} } func (m *RaftDebugRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1829,7 +1829,7 @@ func (m *RaftDebugResponse) Reset() { *m = RaftDebugResponse{} } func (m *RaftDebugResponse) String() string { return proto.CompactTextString(m) } func (*RaftDebugResponse) ProtoMessage() {} func (*RaftDebugResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{43} + return fileDescriptor_status_0225a3e6e509791f, []int{43} } func (m *RaftDebugResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1868,7 +1868,7 @@ func (m *TxnInfo) Reset() { *m = TxnInfo{} } func (m *TxnInfo) String() string { return proto.CompactTextString(m) } func (*TxnInfo) ProtoMessage() {} func (*TxnInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{44} + return fileDescriptor_status_0225a3e6e509791f, []int{44} } func (m *TxnInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1914,7 +1914,7 @@ func (m *ActiveQuery) Reset() { *m = ActiveQuery{} } func (m *ActiveQuery) String() string { return proto.CompactTextString(m) } func (*ActiveQuery) ProtoMessage() {} func (*ActiveQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{45} + return fileDescriptor_status_0225a3e6e509791f, []int{45} } func (m *ActiveQuery) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1949,7 +1949,7 @@ func (m *ListSessionsRequest) Reset() { *m = ListSessionsRequest{} } func (m *ListSessionsRequest) String() string { return proto.CompactTextString(m) } func (*ListSessionsRequest) ProtoMessage() {} func (*ListSessionsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{46} + return fileDescriptor_status_0225a3e6e509791f, []int{46} } func (m *ListSessionsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2008,7 +2008,7 @@ func (m *Session) Reset() { *m = Session{} } func (m *Session) String() string { return proto.CompactTextString(m) } func (*Session) ProtoMessage() {} func (*Session) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{47} + return fileDescriptor_status_0225a3e6e509791f, []int{47} } func (m *Session) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2045,7 +2045,7 @@ func (m *ListSessionsError) Reset() { *m = ListSessionsError{} } func (m *ListSessionsError) String() string { return proto.CompactTextString(m) } func (*ListSessionsError) ProtoMessage() {} func (*ListSessionsError) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{48} + return fileDescriptor_status_0225a3e6e509791f, []int{48} } func (m *ListSessionsError) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2082,7 +2082,7 @@ func (m *ListSessionsResponse) Reset() { *m = ListSessionsResponse{} } func (m *ListSessionsResponse) String() string { return proto.CompactTextString(m) } func (*ListSessionsResponse) ProtoMessage() {} func (*ListSessionsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{49} + return fileDescriptor_status_0225a3e6e509791f, []int{49} } func (m *ListSessionsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2127,7 +2127,7 @@ func (m *CancelQueryRequest) Reset() { *m = CancelQueryRequest{} } func (m *CancelQueryRequest) String() string { return proto.CompactTextString(m) } func (*CancelQueryRequest) ProtoMessage() {} func (*CancelQueryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{50} + return fileDescriptor_status_0225a3e6e509791f, []int{50} } func (m *CancelQueryRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2164,7 +2164,7 @@ func (m *CancelQueryResponse) Reset() { *m = CancelQueryResponse{} } func (m *CancelQueryResponse) String() string { return proto.CompactTextString(m) } func (*CancelQueryResponse) ProtoMessage() {} func (*CancelQueryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{51} + return fileDescriptor_status_0225a3e6e509791f, []int{51} } func (m *CancelQueryResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2204,7 +2204,7 @@ func (m *CancelSessionRequest) Reset() { *m = CancelSessionRequest{} } func (m *CancelSessionRequest) String() string { return proto.CompactTextString(m) } func (*CancelSessionRequest) ProtoMessage() {} func (*CancelSessionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{52} + return fileDescriptor_status_0225a3e6e509791f, []int{52} } func (m *CancelSessionRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2238,7 +2238,7 @@ func (m *CancelSessionResponse) Reset() { *m = CancelSessionResponse{} } func (m *CancelSessionResponse) String() string { return proto.CompactTextString(m) } func (*CancelSessionResponse) ProtoMessage() {} func (*CancelSessionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{53} + return fileDescriptor_status_0225a3e6e509791f, []int{53} } func (m *CancelSessionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2273,7 +2273,7 @@ func (m *SpanStatsRequest) Reset() { *m = SpanStatsRequest{} } func (m *SpanStatsRequest) String() string { return proto.CompactTextString(m) } func (*SpanStatsRequest) ProtoMessage() {} func (*SpanStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{54} + return fileDescriptor_status_0225a3e6e509791f, []int{54} } func (m *SpanStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2308,7 +2308,7 @@ func (m *SpanStatsResponse) Reset() { *m = SpanStatsResponse{} } func (m *SpanStatsResponse) String() string { return proto.CompactTextString(m) } func (*SpanStatsResponse) ProtoMessage() {} func (*SpanStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{55} + return fileDescriptor_status_0225a3e6e509791f, []int{55} } func (m *SpanStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2342,7 +2342,7 @@ func (m *ProblemRangesRequest) Reset() { *m = ProblemRangesRequest{} } func (m *ProblemRangesRequest) String() string { return proto.CompactTextString(m) } func (*ProblemRangesRequest) ProtoMessage() {} func (*ProblemRangesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{56} + return fileDescriptor_status_0225a3e6e509791f, []int{56} } func (m *ProblemRangesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2377,7 +2377,7 @@ func (m *ProblemRangesResponse) Reset() { *m = ProblemRangesResponse{} } func (m *ProblemRangesResponse) String() string { return proto.CompactTextString(m) } func (*ProblemRangesResponse) ProtoMessage() {} func (*ProblemRangesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{57} + return fileDescriptor_status_0225a3e6e509791f, []int{57} } func (m *ProblemRangesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2418,7 +2418,7 @@ func (m *ProblemRangesResponse_NodeProblems) Reset() { *m = ProblemRange func (m *ProblemRangesResponse_NodeProblems) String() string { return proto.CompactTextString(m) } func (*ProblemRangesResponse_NodeProblems) ProtoMessage() {} func (*ProblemRangesResponse_NodeProblems) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{57, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{57, 0} } func (m *ProblemRangesResponse_NodeProblems) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2443,8 +2443,18 @@ func (m *ProblemRangesResponse_NodeProblems) XXX_DiscardUnknown() { var xxx_messageInfo_ProblemRangesResponse_NodeProblems proto.InternalMessageInfo +// HotRangesRequest queries one or more cluster nodes for a list +// of ranges currently considered “hot” by the node(s). +// +// The server responds with a HotRangesResponse payload. type HotRangesRequest struct { - // If left empty, hot ranges for all nodes/stores will be returned. + // NodeID indicates which node to query for a hot range report. + // It is posssible to populate any node ID; if the node receiving + // the request is not the target node, it will forward the + // request to the target node. + // + // If left empty, the request is forwarded to every node + // in the cluster. NodeID string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` } @@ -2452,7 +2462,7 @@ func (m *HotRangesRequest) Reset() { *m = HotRangesRequest{} } func (m *HotRangesRequest) String() string { return proto.CompactTextString(m) } func (*HotRangesRequest) ProtoMessage() {} func (*HotRangesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{58} + return fileDescriptor_status_0225a3e6e509791f, []int{58} } func (m *HotRangesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2477,9 +2487,14 @@ func (m *HotRangesRequest) XXX_DiscardUnknown() { var xxx_messageInfo_HotRangesRequest proto.InternalMessageInfo +// HotRangesResponse is the payload produced in response +// to a HotRangesRequest. type HotRangesResponse struct { - // NodeID is the node that submitted all the requests. - NodeID github_com_cockroachdb_cockroach_pkg_roachpb.NodeID `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3,casttype=github.com/cockroachdb/cockroach/pkg/roachpb.NodeID" json:"node_id,omitempty"` + // NodeID is the node that received the HotRangesRequest and + // forwarded requests to the selected target node(s). + NodeID github_com_cockroachdb_cockroach_pkg_roachpb.NodeID `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3,casttype=github.com/cockroachdb/cockroach/pkg/roachpb.NodeID" json:"node_id,omitempty"` + // HotRangesByNodeID contains a hot range report for each selected + // target node ID in the HotRangesRequest. HotRangesByNodeID map[github_com_cockroachdb_cockroach_pkg_roachpb.NodeID]HotRangesResponse_NodeResponse `protobuf:"bytes,2,rep,name=hot_ranges_by_node_id,json=hotRangesByNodeId,proto3,castkey=github.com/cockroachdb/cockroach/pkg/roachpb.NodeID" json:"hot_ranges_by_node_id" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -2487,7 +2502,7 @@ func (m *HotRangesResponse) Reset() { *m = HotRangesResponse{} } func (m *HotRangesResponse) String() string { return proto.CompactTextString(m) } func (*HotRangesResponse) ProtoMessage() {} func (*HotRangesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{59} + return fileDescriptor_status_0225a3e6e509791f, []int{59} } func (m *HotRangesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2512,16 +2527,26 @@ func (m *HotRangesResponse) XXX_DiscardUnknown() { var xxx_messageInfo_HotRangesResponse proto.InternalMessageInfo +// HotRange is a hot range report for a single store on one of the +// target node(s) selected in a HotRangesRequest. type HotRangesResponse_HotRange struct { - Desc roachpb.RangeDescriptor `protobuf:"bytes,1,opt,name=desc,proto3" json:"desc"` - QueriesPerSecond float64 `protobuf:"fixed64,2,opt,name=queries_per_second,json=queriesPerSecond,proto3" json:"queries_per_second,omitempty"` + // Desc is the descriptor of the range for which the report + // was produced. + // + // Note: this field is generally RESERVED and will likely be removed + // or replaced in a later version. + // See: https://github.com/cockroachdb/cockroach/issues/53212 + Desc roachpb.RangeDescriptor `protobuf:"bytes,1,opt,name=desc,proto3" json:"desc"` + // QueriesPerSecond is the recent number of queries per second + // on this range. + QueriesPerSecond float64 `protobuf:"fixed64,2,opt,name=queries_per_second,json=queriesPerSecond,proto3" json:"queries_per_second,omitempty"` } func (m *HotRangesResponse_HotRange) Reset() { *m = HotRangesResponse_HotRange{} } func (m *HotRangesResponse_HotRange) String() string { return proto.CompactTextString(m) } func (*HotRangesResponse_HotRange) ProtoMessage() {} func (*HotRangesResponse_HotRange) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{59, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{59, 0} } func (m *HotRangesResponse_HotRange) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2546,16 +2571,22 @@ func (m *HotRangesResponse_HotRange) XXX_DiscardUnknown() { var xxx_messageInfo_HotRangesResponse_HotRange proto.InternalMessageInfo +// StoreResponse contains the part of a hot ranges report that +// pertains to a single store on a target node. type HotRangesResponse_StoreResponse struct { - StoreID github_com_cockroachdb_cockroach_pkg_roachpb.StoreID `protobuf:"varint,1,opt,name=store_id,json=storeId,proto3,casttype=github.com/cockroachdb/cockroach/pkg/roachpb.StoreID" json:"store_id,omitempty"` - HotRanges []HotRangesResponse_HotRange `protobuf:"bytes,2,rep,name=hot_ranges,json=hotRanges,proto3" json:"hot_ranges"` + // StoreID identifies the store for which the report was + // produced. + StoreID github_com_cockroachdb_cockroach_pkg_roachpb.StoreID `protobuf:"varint,1,opt,name=store_id,json=storeId,proto3,casttype=github.com/cockroachdb/cockroach/pkg/roachpb.StoreID" json:"store_id,omitempty"` + // HotRanges is the hot ranges report for this store + // on the target node. + HotRanges []HotRangesResponse_HotRange `protobuf:"bytes,2,rep,name=hot_ranges,json=hotRanges,proto3" json:"hot_ranges"` } func (m *HotRangesResponse_StoreResponse) Reset() { *m = HotRangesResponse_StoreResponse{} } func (m *HotRangesResponse_StoreResponse) String() string { return proto.CompactTextString(m) } func (*HotRangesResponse_StoreResponse) ProtoMessage() {} func (*HotRangesResponse_StoreResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{59, 1} + return fileDescriptor_status_0225a3e6e509791f, []int{59, 1} } func (m *HotRangesResponse_StoreResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2580,16 +2611,24 @@ func (m *HotRangesResponse_StoreResponse) XXX_DiscardUnknown() { var xxx_messageInfo_HotRangesResponse_StoreResponse proto.InternalMessageInfo +// NodeResponse is a hot range report for a single target node. type HotRangesResponse_NodeResponse struct { - ErrorMessage string `protobuf:"bytes,1,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` - Stores []*HotRangesResponse_StoreResponse `protobuf:"bytes,2,rep,name=stores,proto3" json:"stores,omitempty"` + // ErrorMessage is set to a non-empty string if this target + // node was unable to produce a hot range report. + // + // The contents of this string indicates the cause of the failure. + ErrorMessage string `protobuf:"bytes,1,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + // Stores contains the hot ranges report if no error was encountered. + // There is one part to the report for each store in the + // target node. + Stores []*HotRangesResponse_StoreResponse `protobuf:"bytes,2,rep,name=stores,proto3" json:"stores,omitempty"` } func (m *HotRangesResponse_NodeResponse) Reset() { *m = HotRangesResponse_NodeResponse{} } func (m *HotRangesResponse_NodeResponse) String() string { return proto.CompactTextString(m) } func (*HotRangesResponse_NodeResponse) ProtoMessage() {} func (*HotRangesResponse_NodeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{59, 2} + return fileDescriptor_status_0225a3e6e509791f, []int{59, 2} } func (m *HotRangesResponse_NodeResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2622,7 +2661,7 @@ func (m *RangeRequest) Reset() { *m = RangeRequest{} } func (m *RangeRequest) String() string { return proto.CompactTextString(m) } func (*RangeRequest) ProtoMessage() {} func (*RangeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{60} + return fileDescriptor_status_0225a3e6e509791f, []int{60} } func (m *RangeRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2658,7 +2697,7 @@ func (m *RangeResponse) Reset() { *m = RangeResponse{} } func (m *RangeResponse) String() string { return proto.CompactTextString(m) } func (*RangeResponse) ProtoMessage() {} func (*RangeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{61} + return fileDescriptor_status_0225a3e6e509791f, []int{61} } func (m *RangeResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2693,7 +2732,7 @@ func (m *RangeResponse_NodeResponse) Reset() { *m = RangeResponse_NodeRe func (m *RangeResponse_NodeResponse) String() string { return proto.CompactTextString(m) } func (*RangeResponse_NodeResponse) ProtoMessage() {} func (*RangeResponse_NodeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{61, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{61, 0} } func (m *RangeResponse_NodeResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2729,7 +2768,7 @@ func (m *DiagnosticsRequest) Reset() { *m = DiagnosticsRequest{} } func (m *DiagnosticsRequest) String() string { return proto.CompactTextString(m) } func (*DiagnosticsRequest) ProtoMessage() {} func (*DiagnosticsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{62} + return fileDescriptor_status_0225a3e6e509791f, []int{62} } func (m *DiagnosticsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2764,7 +2803,7 @@ func (m *StoresRequest) Reset() { *m = StoresRequest{} } func (m *StoresRequest) String() string { return proto.CompactTextString(m) } func (*StoresRequest) ProtoMessage() {} func (*StoresRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{63} + return fileDescriptor_status_0225a3e6e509791f, []int{63} } func (m *StoresRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2807,7 +2846,7 @@ func (m *StoreDetails) Reset() { *m = StoreDetails{} } func (m *StoreDetails) String() string { return proto.CompactTextString(m) } func (*StoreDetails) ProtoMessage() {} func (*StoreDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{64} + return fileDescriptor_status_0225a3e6e509791f, []int{64} } func (m *StoreDetails) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2840,7 +2879,7 @@ func (m *StoresResponse) Reset() { *m = StoresResponse{} } func (m *StoresResponse) String() string { return proto.CompactTextString(m) } func (*StoresResponse) ProtoMessage() {} func (*StoresResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{65} + return fileDescriptor_status_0225a3e6e509791f, []int{65} } func (m *StoresResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2873,7 +2912,7 @@ func (m *StatementsRequest) Reset() { *m = StatementsRequest{} } func (m *StatementsRequest) String() string { return proto.CompactTextString(m) } func (*StatementsRequest) ProtoMessage() {} func (*StatementsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{66} + return fileDescriptor_status_0225a3e6e509791f, []int{66} } func (m *StatementsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2914,7 +2953,7 @@ func (m *StatementsResponse) Reset() { *m = StatementsResponse{} } func (m *StatementsResponse) String() string { return proto.CompactTextString(m) } func (*StatementsResponse) ProtoMessage() {} func (*StatementsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{67} + return fileDescriptor_status_0225a3e6e509791f, []int{67} } func (m *StatementsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2952,7 +2991,7 @@ func (m *StatementsResponse_ExtendedStatementStatisticsKey) String() string { } func (*StatementsResponse_ExtendedStatementStatisticsKey) ProtoMessage() {} func (*StatementsResponse_ExtendedStatementStatisticsKey) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{67, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{67, 0} } func (m *StatementsResponse_ExtendedStatementStatisticsKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2990,7 +3029,7 @@ func (m *StatementsResponse_CollectedStatementStatistics) String() string { } func (*StatementsResponse_CollectedStatementStatistics) ProtoMessage() {} func (*StatementsResponse_CollectedStatementStatistics) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{67, 1} + return fileDescriptor_status_0225a3e6e509791f, []int{67, 1} } func (m *StatementsResponse_CollectedStatementStatistics) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3028,7 +3067,7 @@ func (m *StatementsResponse_ExtendedCollectedTransactionStatistics) String() str } func (*StatementsResponse_ExtendedCollectedTransactionStatistics) ProtoMessage() {} func (*StatementsResponse_ExtendedCollectedTransactionStatistics) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{67, 2} + return fileDescriptor_status_0225a3e6e509791f, []int{67, 2} } func (m *StatementsResponse_ExtendedCollectedTransactionStatistics) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3065,7 +3104,7 @@ func (m *StatementDiagnosticsReport) Reset() { *m = StatementDiagnostics func (m *StatementDiagnosticsReport) String() string { return proto.CompactTextString(m) } func (*StatementDiagnosticsReport) ProtoMessage() {} func (*StatementDiagnosticsReport) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{68} + return fileDescriptor_status_0225a3e6e509791f, []int{68} } func (m *StatementDiagnosticsReport) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3100,7 +3139,7 @@ func (m *CreateStatementDiagnosticsReportRequest) Reset() { func (m *CreateStatementDiagnosticsReportRequest) String() string { return proto.CompactTextString(m) } func (*CreateStatementDiagnosticsReportRequest) ProtoMessage() {} func (*CreateStatementDiagnosticsReportRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{69} + return fileDescriptor_status_0225a3e6e509791f, []int{69} } func (m *CreateStatementDiagnosticsReportRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3135,7 +3174,7 @@ func (m *CreateStatementDiagnosticsReportResponse) Reset() { func (m *CreateStatementDiagnosticsReportResponse) String() string { return proto.CompactTextString(m) } func (*CreateStatementDiagnosticsReportResponse) ProtoMessage() {} func (*CreateStatementDiagnosticsReportResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{70} + return fileDescriptor_status_0225a3e6e509791f, []int{70} } func (m *CreateStatementDiagnosticsReportResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3167,7 +3206,7 @@ func (m *StatementDiagnosticsReportsRequest) Reset() { *m = StatementDia func (m *StatementDiagnosticsReportsRequest) String() string { return proto.CompactTextString(m) } func (*StatementDiagnosticsReportsRequest) ProtoMessage() {} func (*StatementDiagnosticsReportsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{71} + return fileDescriptor_status_0225a3e6e509791f, []int{71} } func (m *StatementDiagnosticsReportsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3200,7 +3239,7 @@ func (m *StatementDiagnosticsReportsResponse) Reset() { *m = StatementDi func (m *StatementDiagnosticsReportsResponse) String() string { return proto.CompactTextString(m) } func (*StatementDiagnosticsReportsResponse) ProtoMessage() {} func (*StatementDiagnosticsReportsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{72} + return fileDescriptor_status_0225a3e6e509791f, []int{72} } func (m *StatementDiagnosticsReportsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3236,7 +3275,7 @@ func (m *StatementDiagnostics) Reset() { *m = StatementDiagnostics{} } func (m *StatementDiagnostics) String() string { return proto.CompactTextString(m) } func (*StatementDiagnostics) ProtoMessage() {} func (*StatementDiagnostics) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{73} + return fileDescriptor_status_0225a3e6e509791f, []int{73} } func (m *StatementDiagnostics) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3269,7 +3308,7 @@ func (m *StatementDiagnosticsRequest) Reset() { *m = StatementDiagnostic func (m *StatementDiagnosticsRequest) String() string { return proto.CompactTextString(m) } func (*StatementDiagnosticsRequest) ProtoMessage() {} func (*StatementDiagnosticsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{74} + return fileDescriptor_status_0225a3e6e509791f, []int{74} } func (m *StatementDiagnosticsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3302,7 +3341,7 @@ func (m *StatementDiagnosticsResponse) Reset() { *m = StatementDiagnosti func (m *StatementDiagnosticsResponse) String() string { return proto.CompactTextString(m) } func (*StatementDiagnosticsResponse) ProtoMessage() {} func (*StatementDiagnosticsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{75} + return fileDescriptor_status_0225a3e6e509791f, []int{75} } func (m *StatementDiagnosticsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3335,7 +3374,7 @@ func (m *JobRegistryStatusRequest) Reset() { *m = JobRegistryStatusReque func (m *JobRegistryStatusRequest) String() string { return proto.CompactTextString(m) } func (*JobRegistryStatusRequest) ProtoMessage() {} func (*JobRegistryStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{76} + return fileDescriptor_status_0225a3e6e509791f, []int{76} } func (m *JobRegistryStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3369,7 +3408,7 @@ func (m *JobRegistryStatusResponse) Reset() { *m = JobRegistryStatusResp func (m *JobRegistryStatusResponse) String() string { return proto.CompactTextString(m) } func (*JobRegistryStatusResponse) ProtoMessage() {} func (*JobRegistryStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{77} + return fileDescriptor_status_0225a3e6e509791f, []int{77} } func (m *JobRegistryStatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3402,7 +3441,7 @@ func (m *JobRegistryStatusResponse_Job) Reset() { *m = JobRegistryStatus func (m *JobRegistryStatusResponse_Job) String() string { return proto.CompactTextString(m) } func (*JobRegistryStatusResponse_Job) ProtoMessage() {} func (*JobRegistryStatusResponse_Job) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{77, 0} + return fileDescriptor_status_0225a3e6e509791f, []int{77, 0} } func (m *JobRegistryStatusResponse_Job) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3435,7 +3474,7 @@ func (m *JobStatusRequest) Reset() { *m = JobStatusRequest{} } func (m *JobStatusRequest) String() string { return proto.CompactTextString(m) } func (*JobStatusRequest) ProtoMessage() {} func (*JobStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{78} + return fileDescriptor_status_0225a3e6e509791f, []int{78} } func (m *JobStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3468,7 +3507,7 @@ func (m *JobStatusResponse) Reset() { *m = JobStatusResponse{} } func (m *JobStatusResponse) String() string { return proto.CompactTextString(m) } func (*JobStatusResponse) ProtoMessage() {} func (*JobStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_status_bcb064aca6987b84, []int{79} + return fileDescriptor_status_0225a3e6e509791f, []int{79} } func (m *JobStatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -22006,10 +22045,10 @@ var ( ) func init() { - proto.RegisterFile("server/serverpb/status.proto", fileDescriptor_status_bcb064aca6987b84) + proto.RegisterFile("server/serverpb/status.proto", fileDescriptor_status_0225a3e6e509791f) } -var fileDescriptor_status_bcb064aca6987b84 = []byte{ +var fileDescriptor_status_0225a3e6e509791f = []byte{ // 5982 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x7c, 0xdb, 0x6f, 0x1b, 0x49, 0x76, 0xb7, 0x9b, 0xa4, 0x28, 0xf2, 0x50, 0x17, 0xaa, 0x2c, 0xc9, 0x34, 0xed, 0x11, 0xbd, 0xed, diff --git a/pkg/server/serverpb/status.proto b/pkg/server/serverpb/status.proto index 87f6ffcf70de..b6c40f01a91b 100644 --- a/pkg/server/serverpb/status.proto +++ b/pkg/server/serverpb/status.proto @@ -692,34 +692,80 @@ message ProblemRangesResponse { ]; } +// HotRangesRequest queries one or more cluster nodes for a list +// of ranges currently considered “hot” by the node(s). +// +// The server responds with a HotRangesResponse payload. message HotRangesRequest { - // If left empty, hot ranges for all nodes/stores will be returned. + // NodeID indicates which node to query for a hot range report. + // It is posssible to populate any node ID; if the node receiving + // the request is not the target node, it will forward the + // request to the target node. + // + // If left empty, the request is forwarded to every node + // in the cluster. string node_id = 1 [(gogoproto.customname) = "NodeID"]; } +// HotRangesResponse is the payload produced in response +// to a HotRangesRequest. message HotRangesResponse { + // NodeID is the node that received the HotRangesRequest and + // forwarded requests to the selected target node(s). + int32 node_id = 1 [ + (gogoproto.customname) = "NodeID", + (gogoproto.casttype) = + "github.com/cockroachdb/cockroach/pkg/roachpb.NodeID" + ]; + + // HotRange is a hot range report for a single store on one of the + // target node(s) selected in a HotRangesRequest. message HotRange { + // Desc is the descriptor of the range for which the report + // was produced. + // + // Note: this field is generally RESERVED and will likely be removed + // or replaced in a later version. + // See: https://github.com/cockroachdb/cockroach/issues/53212 cockroach.roachpb.RangeDescriptor desc = 1 [(gogoproto.nullable) = false]; + + // QueriesPerSecond is the recent number of queries per second + // on this range. double queries_per_second = 2; } + + // StoreResponse contains the part of a hot ranges report that + // pertains to a single store on a target node. message StoreResponse { + // StoreID identifies the store for which the report was + // produced. int32 store_id = 1 [ (gogoproto.customname) = "StoreID", (gogoproto.casttype) = "github.com/cockroachdb/cockroach/pkg/roachpb.StoreID" ]; + + // HotRanges is the hot ranges report for this store + // on the target node. repeated HotRange hot_ranges = 2 [(gogoproto.nullable) = false]; } + + // NodeResponse is a hot range report for a single target node. message NodeResponse { + // ErrorMessage is set to a non-empty string if this target + // node was unable to produce a hot range report. + // + // The contents of this string indicates the cause of the failure. string error_message = 1; + + // Stores contains the hot ranges report if no error was encountered. + // There is one part to the report for each store in the + // target node. repeated StoreResponse stores = 2; } - // NodeID is the node that submitted all the requests. - int32 node_id = 1 [ - (gogoproto.customname) = "NodeID", - (gogoproto.casttype) = - "github.com/cockroachdb/cockroach/pkg/roachpb.NodeID" - ]; + + // HotRangesByNodeID contains a hot range report for each selected + // target node ID in the HotRangesRequest. map hot_ranges_by_node_id = 2 [ (gogoproto.castkey) = "github.com/cockroachdb/cockroach/pkg/roachpb.NodeID", (gogoproto.customname) = "HotRangesByNodeID", diff --git a/pkg/sql/authorization.go b/pkg/sql/authorization.go index 80a9b6dfbb76..f9d5cd243a4b 100644 --- a/pkg/sql/authorization.go +++ b/pkg/sql/authorization.go @@ -561,3 +561,41 @@ func (p *planner) checkCanAlterToNewOwner( return nil } + +// HasOwnershipOnSchema checks if the current user has ownership on the schema. +// For schemas, we cannot always use HasOwnership as not every schema has a +// descriptor. +func (p *planner) HasOwnershipOnSchema(ctx context.Context, schemaID descpb.ID) (bool, error) { + resolvedSchema, err := p.Descriptors().ResolveSchemaByID( + ctx, p.Txn(), schemaID, + ) + if err != nil { + return false, err + } + + hasOwnership := false + switch resolvedSchema.Kind { + case sqlbase.SchemaPublic: + // admin is the owner of the public schema. + hasOwnership, err = p.UserHasAdminRole(ctx, p.User()) + if err != nil { + return false, err + } + case sqlbase.SchemaVirtual: + // Cannot drop on virtual schemas. + case sqlbase.SchemaTemporary: + // The user only owns the temporary schema that corresponds to the + // TemporarySchemaID in the sessionData. + hasOwnership = p.SessionData() != nil && + p.SessionData().TemporarySchemaID == uint32(resolvedSchema.ID) + case sqlbase.SchemaUserDefined: + hasOwnership, err = p.HasOwnership(ctx, resolvedSchema.Desc) + if err != nil { + return false, err + } + default: + panic(errors.AssertionFailedf("unknown schema kind %d", resolvedSchema.Kind)) + } + + return hasOwnership, nil +} diff --git a/pkg/sql/catalog/descs/collection.go b/pkg/sql/catalog/descs/collection.go index 8f88a7dcae0e..8260e3867a88 100644 --- a/pkg/sql/catalog/descs/collection.go +++ b/pkg/sql/catalog/descs/collection.go @@ -885,6 +885,7 @@ func (tc *Collection) ResolveSchemaByID( // If this collection is attached to a session and the session has created // a temporary schema, then check if the schema ID matches. + // This check doesn't work after switching databases. Issue #53163. if tc.sessionData != nil && tc.sessionData.TemporarySchemaID == uint32(schemaID) { return catalog.ResolvedSchema{ Kind: catalog.SchemaTemporary, diff --git a/pkg/sql/distsql/columnar_operators_test.go b/pkg/sql/distsql/columnar_operators_test.go index ecd56c6b1de6..39c9c4b0ff67 100644 --- a/pkg/sql/distsql/columnar_operators_test.go +++ b/pkg/sql/distsql/columnar_operators_test.go @@ -68,6 +68,7 @@ var aggregateFuncToNumArguments = map[execinfrapb.AggregatorSpec_Func]int{ execinfrapb.AggregatorSpec_STDDEV_POP: 1, execinfrapb.AggregatorSpec_ST_MAKELINE: 1, execinfrapb.AggregatorSpec_ST_EXTENT: 1, + execinfrapb.AggregatorSpec_ST_UNION: 1, } // TestAggregateFuncToNumArguments ensures that all aggregate functions are @@ -183,9 +184,9 @@ func TestAggregatorAgainstProcessor(t *testing.T) { for j := range aggFnInputTypes { aggFnInputTypes[j] = sqlbase.RandType(rng) } - // There is a special case for concat_agg, string_agg, - // st_makeline, and st_extent when at least one argument is a - // tuple. Such cases pass GetAggregateInfo check below, + // There is a special case for some functions when at + // least one argument is a tuple. + // Such cases pass GetAggregateInfo check below, // but they are actually invalid, and during normal // execution it is caught during type-checking. // However, we don't want to do fully-fledged type @@ -195,7 +196,8 @@ func TestAggregatorAgainstProcessor(t *testing.T) { case execinfrapb.AggregatorSpec_CONCAT_AGG, execinfrapb.AggregatorSpec_STRING_AGG, execinfrapb.AggregatorSpec_ST_MAKELINE, - execinfrapb.AggregatorSpec_ST_EXTENT: + execinfrapb.AggregatorSpec_ST_EXTENT, + execinfrapb.AggregatorSpec_ST_UNION: for _, typ := range aggFnInputTypes { if typ.Family() == types.TupleFamily { invalid = true diff --git a/pkg/sql/drop_cascade.go b/pkg/sql/drop_cascade.go index 8a485aa7631d..dc4448567189 100644 --- a/pkg/sql/drop_cascade.go +++ b/pkg/sql/drop_cascade.go @@ -99,7 +99,7 @@ func (d *dropCascadeState) resolveCollectedObjects( " dropped or made public before dropping database %s", objName.FQString(), tree.AsString((*tree.Name)(&dbName))) } - if err := p.prepareDropWithTableDesc(ctx, tbDesc); err != nil { + if err := p.canDropTable(ctx, tbDesc); err != nil { return err } // Recursively check permissions on all dependent views, since some may diff --git a/pkg/sql/drop_table.go b/pkg/sql/drop_table.go index 87cc872041a9..ac70336ea054 100644 --- a/pkg/sql/drop_table.go +++ b/pkg/sql/drop_table.go @@ -172,20 +172,33 @@ func (p *planner) prepareDrop( if tableDesc == nil { return nil, err } - if err := p.prepareDropWithTableDesc(ctx, tableDesc); err != nil { + if err := p.canDropTable(ctx, tableDesc); err != nil { return nil, err } return tableDesc, nil } -// prepareDropWithTableDesc behaves as prepareDrop, except it assumes the -// table descriptor is already fetched. This is useful for DropDatabase, -// as prepareDrop requires resolving a TableName when DropDatabase already -// has it resolved. -func (p *planner) prepareDropWithTableDesc( +// canDropTable returns an error if the user cannot drop the table. +func (p *planner) canDropTable( ctx context.Context, tableDesc *sqlbase.MutableTableDescriptor, ) error { - return p.CheckPrivilege(ctx, tableDesc, privilege.DROP) + // Don't check for ownership if the table is a temp table. + // ResolveSchema currently doesn't work for temp schemas. + // Hack until #53163 is fixed. + hasOwnership := false + var err error + if !tableDesc.Temporary { + // If the user owns the schema the table is part of, they can drop the table. + hasOwnership, err = p.HasOwnershipOnSchema(ctx, tableDesc.GetParentSchemaID()) + if err != nil { + return err + } + } + if !hasOwnership { + return p.CheckPrivilege(ctx, tableDesc, privilege.DROP) + } + + return nil } // canRemoveFKBackReference returns an error if the input backreference isn't diff --git a/pkg/sql/execinfra/server_config.go b/pkg/sql/execinfra/server_config.go index c014d4c5cd8d..44d616240cff 100644 --- a/pkg/sql/execinfra/server_config.go +++ b/pkg/sql/execinfra/server_config.go @@ -64,7 +64,7 @@ import ( // // ATTENTION: When updating these fields, add to version_history.txt explaining // what changed. -const Version execinfrapb.DistSQLVersion = 32 +const Version execinfrapb.DistSQLVersion = 33 // MinAcceptedVersion is the oldest version that the server is // compatible with; see above. diff --git a/pkg/sql/execinfra/version_history.txt b/pkg/sql/execinfra/version_history.txt index deb5c8bf7ebf..9cf3c469e7a0 100644 --- a/pkg/sql/execinfra/version_history.txt +++ b/pkg/sql/execinfra/version_history.txt @@ -123,3 +123,6 @@ - Version: 32 (MinAcceptedVersion: 30) - Added an aggregator for ST_Extent. The change is backwards compatible (mixed versions will prevent parallelization). +- Version: 33 (MinAcceptedVersion: 30) + - Added an aggregator for ST_Union. The change is backwards compatible + (mixed versions will prevent parallelization). diff --git a/pkg/sql/execinfrapb/processors_sql.pb.go b/pkg/sql/execinfrapb/processors_sql.pb.go index 148c540a4c42..0eb801b2b4d4 100644 --- a/pkg/sql/execinfrapb/processors_sql.pb.go +++ b/pkg/sql/execinfrapb/processors_sql.pb.go @@ -64,7 +64,7 @@ func (x *ScanVisibility) UnmarshalJSON(data []byte) error { return nil } func (ScanVisibility) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{0} } // These mirror the aggregate functions supported by sql/parser. See @@ -105,6 +105,7 @@ const ( AggregatorSpec_STDDEV_POP AggregatorSpec_Func = 30 AggregatorSpec_ST_MAKELINE AggregatorSpec_Func = 31 AggregatorSpec_ST_EXTENT AggregatorSpec_Func = 32 + AggregatorSpec_ST_UNION AggregatorSpec_Func = 33 ) var AggregatorSpec_Func_name = map[int32]string{ @@ -140,6 +141,7 @@ var AggregatorSpec_Func_name = map[int32]string{ 30: "STDDEV_POP", 31: "ST_MAKELINE", 32: "ST_EXTENT", + 33: "ST_UNION", } var AggregatorSpec_Func_value = map[string]int32{ "ANY_NOT_NULL": 0, @@ -174,6 +176,7 @@ var AggregatorSpec_Func_value = map[string]int32{ "STDDEV_POP": 30, "ST_MAKELINE": 31, "ST_EXTENT": 32, + "ST_UNION": 33, } func (x AggregatorSpec_Func) Enum() *AggregatorSpec_Func { @@ -193,7 +196,7 @@ func (x *AggregatorSpec_Func) UnmarshalJSON(data []byte) error { return nil } func (AggregatorSpec_Func) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{12, 0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{12, 0} } type AggregatorSpec_Type int32 @@ -239,7 +242,7 @@ func (x *AggregatorSpec_Type) UnmarshalJSON(data []byte) error { return nil } func (AggregatorSpec_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{12, 1} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{12, 1} } type WindowerSpec_WindowFunc int32 @@ -303,7 +306,7 @@ func (x *WindowerSpec_WindowFunc) UnmarshalJSON(data []byte) error { return nil } func (WindowerSpec_WindowFunc) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 0} } // Mode indicates which mode of framing is used. @@ -347,7 +350,7 @@ func (x *WindowerSpec_Frame_Mode) UnmarshalJSON(data []byte) error { return nil } func (WindowerSpec_Frame_Mode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 1, 0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 1, 0} } // BoundType indicates which type of boundary is used. @@ -394,7 +397,7 @@ func (x *WindowerSpec_Frame_BoundType) UnmarshalJSON(data []byte) error { return nil } func (WindowerSpec_Frame_BoundType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 1, 1} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 1, 1} } // Exclusion specifies the type of frame exclusion. @@ -437,7 +440,7 @@ func (x *WindowerSpec_Frame_Exclusion) UnmarshalJSON(data []byte) error { return nil } func (WindowerSpec_Frame_Exclusion) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 1, 2} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 1, 2} } // ValuesCoreSpec is the core of a processor that has no inputs and generates @@ -457,7 +460,7 @@ func (m *ValuesCoreSpec) Reset() { *m = ValuesCoreSpec{} } func (m *ValuesCoreSpec) String() string { return proto.CompactTextString(m) } func (*ValuesCoreSpec) ProtoMessage() {} func (*ValuesCoreSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{0} } func (m *ValuesCoreSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -565,7 +568,7 @@ func (m *TableReaderSpec) Reset() { *m = TableReaderSpec{} } func (m *TableReaderSpec) String() string { return proto.CompactTextString(m) } func (*TableReaderSpec) ProtoMessage() {} func (*TableReaderSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{1} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{1} } func (m *TableReaderSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -620,7 +623,7 @@ func (m *IndexSkipTableReaderSpec) Reset() { *m = IndexSkipTableReaderSp func (m *IndexSkipTableReaderSpec) String() string { return proto.CompactTextString(m) } func (*IndexSkipTableReaderSpec) ProtoMessage() {} func (*IndexSkipTableReaderSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{2} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{2} } func (m *IndexSkipTableReaderSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -727,7 +730,7 @@ func (m *JoinReaderSpec) Reset() { *m = JoinReaderSpec{} } func (m *JoinReaderSpec) String() string { return proto.CompactTextString(m) } func (*JoinReaderSpec) ProtoMessage() {} func (*JoinReaderSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{3} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{3} } func (m *JoinReaderSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -771,7 +774,7 @@ func (m *SorterSpec) Reset() { *m = SorterSpec{} } func (m *SorterSpec) String() string { return proto.CompactTextString(m) } func (*SorterSpec) ProtoMessage() {} func (*SorterSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{4} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{4} } func (m *SorterSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -833,7 +836,7 @@ func (m *DistinctSpec) Reset() { *m = DistinctSpec{} } func (m *DistinctSpec) String() string { return proto.CompactTextString(m) } func (*DistinctSpec) ProtoMessage() {} func (*DistinctSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{5} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{5} } func (m *DistinctSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -868,7 +871,7 @@ func (m *OrdinalitySpec) Reset() { *m = OrdinalitySpec{} } func (m *OrdinalitySpec) String() string { return proto.CompactTextString(m) } func (*OrdinalitySpec) ProtoMessage() {} func (*OrdinalitySpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{6} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{6} } func (m *OrdinalitySpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -926,7 +929,7 @@ func (m *ZigzagJoinerSpec) Reset() { *m = ZigzagJoinerSpec{} } func (m *ZigzagJoinerSpec) String() string { return proto.CompactTextString(m) } func (*ZigzagJoinerSpec) ProtoMessage() {} func (*ZigzagJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{7} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{7} } func (m *ZigzagJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1002,7 +1005,7 @@ func (m *MergeJoinerSpec) Reset() { *m = MergeJoinerSpec{} } func (m *MergeJoinerSpec) String() string { return proto.CompactTextString(m) } func (*MergeJoinerSpec) ProtoMessage() {} func (*MergeJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{8} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{8} } func (m *MergeJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1089,7 +1092,7 @@ func (m *HashJoinerSpec) Reset() { *m = HashJoinerSpec{} } func (m *HashJoinerSpec) String() string { return proto.CompactTextString(m) } func (*HashJoinerSpec) ProtoMessage() {} func (*HashJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{9} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{9} } func (m *HashJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1183,7 +1186,7 @@ func (m *InvertedJoinerSpec) Reset() { *m = InvertedJoinerSpec{} } func (m *InvertedJoinerSpec) String() string { return proto.CompactTextString(m) } func (*InvertedJoinerSpec) ProtoMessage() {} func (*InvertedJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{10} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{10} } func (m *InvertedJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1236,7 +1239,7 @@ func (m *InvertedFiltererSpec) Reset() { *m = InvertedFiltererSpec{} } func (m *InvertedFiltererSpec) String() string { return proto.CompactTextString(m) } func (*InvertedFiltererSpec) ProtoMessage() {} func (*InvertedFiltererSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{11} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{11} } func (m *InvertedFiltererSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1282,7 +1285,7 @@ func (m *AggregatorSpec) Reset() { *m = AggregatorSpec{} } func (m *AggregatorSpec) String() string { return proto.CompactTextString(m) } func (*AggregatorSpec) ProtoMessage() {} func (*AggregatorSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{12} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{12} } func (m *AggregatorSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1333,7 +1336,7 @@ func (m *AggregatorSpec_Aggregation) Reset() { *m = AggregatorSpec_Aggre func (m *AggregatorSpec_Aggregation) String() string { return proto.CompactTextString(m) } func (*AggregatorSpec_Aggregation) ProtoMessage() {} func (*AggregatorSpec_Aggregation) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{12, 0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{12, 0} } func (m *AggregatorSpec_Aggregation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1404,7 +1407,7 @@ func (m *InterleavedReaderJoinerSpec) Reset() { *m = InterleavedReaderJo func (m *InterleavedReaderJoinerSpec) String() string { return proto.CompactTextString(m) } func (*InterleavedReaderJoinerSpec) ProtoMessage() {} func (*InterleavedReaderJoinerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{13} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{13} } func (m *InterleavedReaderJoinerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1460,7 +1463,7 @@ func (m *InterleavedReaderJoinerSpec_Table) Reset() { *m = InterleavedRe func (m *InterleavedReaderJoinerSpec_Table) String() string { return proto.CompactTextString(m) } func (*InterleavedReaderJoinerSpec_Table) ProtoMessage() {} func (*InterleavedReaderJoinerSpec_Table) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{13, 0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{13, 0} } func (m *InterleavedReaderJoinerSpec_Table) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1500,7 +1503,7 @@ func (m *ProjectSetSpec) Reset() { *m = ProjectSetSpec{} } func (m *ProjectSetSpec) String() string { return proto.CompactTextString(m) } func (*ProjectSetSpec) ProtoMessage() {} func (*ProjectSetSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{14} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{14} } func (m *ProjectSetSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1542,7 +1545,7 @@ func (m *WindowerSpec) Reset() { *m = WindowerSpec{} } func (m *WindowerSpec) String() string { return proto.CompactTextString(m) } func (*WindowerSpec) ProtoMessage() {} func (*WindowerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15} } func (m *WindowerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1578,7 +1581,7 @@ func (m *WindowerSpec_Func) Reset() { *m = WindowerSpec_Func{} } func (m *WindowerSpec_Func) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_Func) ProtoMessage() {} func (*WindowerSpec_Func) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 0} } func (m *WindowerSpec_Func) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1614,7 +1617,7 @@ func (m *WindowerSpec_Frame) Reset() { *m = WindowerSpec_Frame{} } func (m *WindowerSpec_Frame) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_Frame) ProtoMessage() {} func (*WindowerSpec_Frame) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 1} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 1} } func (m *WindowerSpec_Frame) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1655,7 +1658,7 @@ func (m *WindowerSpec_Frame_Bound) Reset() { *m = WindowerSpec_Frame_Bou func (m *WindowerSpec_Frame_Bound) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_Frame_Bound) ProtoMessage() {} func (*WindowerSpec_Frame_Bound) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 1, 0} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 1, 0} } func (m *WindowerSpec_Frame_Bound) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1691,7 +1694,7 @@ func (m *WindowerSpec_Frame_Bounds) Reset() { *m = WindowerSpec_Frame_Bo func (m *WindowerSpec_Frame_Bounds) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_Frame_Bounds) ProtoMessage() {} func (*WindowerSpec_Frame_Bounds) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 1, 1} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 1, 1} } func (m *WindowerSpec_Frame_Bounds) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1741,7 +1744,7 @@ func (m *WindowerSpec_WindowFn) Reset() { *m = WindowerSpec_WindowFn{} } func (m *WindowerSpec_WindowFn) String() string { return proto.CompactTextString(m) } func (*WindowerSpec_WindowFn) ProtoMessage() {} func (*WindowerSpec_WindowFn) Descriptor() ([]byte, []int) { - return fileDescriptor_processors_sql_d6f5455294315145, []int{15, 2} + return fileDescriptor_processors_sql_87f40537b51e0560, []int{15, 2} } func (m *WindowerSpec_WindowFn) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -8083,180 +8086,180 @@ var ( ) func init() { - proto.RegisterFile("sql/execinfrapb/processors_sql.proto", fileDescriptor_processors_sql_d6f5455294315145) -} - -var fileDescriptor_processors_sql_d6f5455294315145 = []byte{ - // 2726 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0xcf, 0x73, 0xdb, 0xc6, - 0xf5, 0x17, 0xf8, 0x43, 0x22, 0x1f, 0x7f, 0x68, 0xbd, 0x56, 0x62, 0x86, 0xf9, 0x7e, 0x65, 0x99, - 0x49, 0x63, 0xd9, 0x71, 0xa4, 0x46, 0xed, 0xa4, 0x93, 0xa4, 0x87, 0x80, 0x24, 0x28, 0x53, 0xa6, - 0x00, 0x1a, 0x24, 0x65, 0x27, 0x99, 0x09, 0x06, 0x22, 0x56, 0x14, 0x62, 0x10, 0xa0, 0x00, 0xd0, - 0x92, 0xf2, 0x0f, 0xf4, 0xda, 0x4e, 0x2f, 0x3d, 0x75, 0x72, 0x69, 0x6f, 0xbd, 0xf5, 0x9c, 0x5e, - 0x7a, 0xf0, 0x31, 0xd3, 0x43, 0x9b, 0x53, 0xa7, 0xb1, 0xfb, 0x0f, 0xf4, 0x94, 0xe9, 0xad, 0xb3, - 0x8b, 0x05, 0x04, 0x72, 0x44, 0xd7, 0xb4, 0x95, 0x78, 0x7a, 0xd1, 0x70, 0xdf, 0x8f, 0xcf, 0xbe, - 0x7d, 0xef, 0xed, 0xdb, 0xb7, 0x0b, 0xc1, 0x9b, 0xde, 0x91, 0xb5, 0x49, 0x4e, 0x48, 0xdf, 0xb4, - 0x0f, 0x5c, 0x7d, 0xb4, 0xbf, 0x39, 0x72, 0x9d, 0x3e, 0xf1, 0x3c, 0xc7, 0xf5, 0x34, 0xef, 0xc8, - 0xda, 0x18, 0xb9, 0x8e, 0xef, 0xe0, 0x52, 0xdf, 0xe9, 0x3f, 0x70, 0x1d, 0xbd, 0x7f, 0xb8, 0x41, - 0x89, 0x86, 0xe9, 0xf9, 0xde, 0x91, 0xe5, 0x8e, 0xed, 0xf2, 0x1b, 0x54, 0xbf, 0xaf, 0xfb, 0xba, - 0xe5, 0x0c, 0x36, 0x0d, 0xe2, 0xf5, 0x47, 0xfb, 0x9b, 0x9e, 0xef, 0x8e, 0xfb, 0xfe, 0xd8, 0x25, - 0x46, 0xa0, 0x5e, 0xae, 0x9c, 0x23, 0xf4, 0xb9, 0x63, 0xda, 0x9a, 0x7f, 0x3a, 0x22, 0x5c, 0x66, - 0xed, 0x1c, 0x19, 0xcb, 0xe9, 0x3f, 0x30, 0xed, 0x01, 0x97, 0x78, 0x85, 0x4a, 0x50, 0x0d, 0x2f, - 0xf8, 0xcb, 0xc9, 0xe5, 0xe9, 0x15, 0x18, 0xba, 0xaf, 0x73, 0xde, 0x8f, 0x9e, 0xb2, 0xba, 0x7d, - 0xdd, 0x0b, 0xe7, 0xbe, 0x49, 0xc5, 0x9c, 0x91, 0xbf, 0x69, 0xda, 0x0f, 0x89, 0xeb, 0x13, 0x83, - 0x9c, 0x8c, 0xdc, 0x4d, 0x6f, 0xa4, 0xdb, 0x1a, 0xfd, 0x45, 0x3c, 0xcf, 0x74, 0x6c, 0x2e, 0xbb, - 0x32, 0x70, 0x06, 0x0e, 0xfb, 0xb9, 0x49, 0x7f, 0x05, 0xd4, 0xca, 0xaf, 0x05, 0x28, 0xee, 0xe9, - 0xd6, 0x98, 0x78, 0x35, 0xc7, 0x25, 0x9d, 0x11, 0xe9, 0xe3, 0x1a, 0x2c, 0xf5, 0x1d, 0x6b, 0x3c, - 0xb4, 0xbd, 0x92, 0xb0, 0x96, 0x5c, 0xcf, 0x6d, 0xbd, 0xb1, 0x31, 0xcb, 0x8b, 0x1b, 0x75, 0xdd, - 0x1f, 0x0f, 0x9b, 0xf6, 0x81, 0x53, 0x4d, 0x3d, 0xfa, 0xfb, 0xd5, 0x05, 0x35, 0xd4, 0xc4, 0xaf, - 0x43, 0xd6, 0xd5, 0x8f, 0xb5, 0xfd, 0x53, 0x9f, 0x78, 0xa5, 0xc4, 0x5a, 0x72, 0x3d, 0xaf, 0x66, - 0x5c, 0xfd, 0xb8, 0x4a, 0xc7, 0xf8, 0x2a, 0x64, 0xec, 0xf1, 0x50, 0x73, 0x9d, 0x63, 0xaf, 0x94, - 0x5c, 0x13, 0xd6, 0x53, 0xa1, 0xb6, 0x3d, 0x1e, 0xaa, 0xce, 0xb1, 0x57, 0xf9, 0x57, 0x1a, 0x96, - 0xbb, 0xfa, 0xbe, 0x45, 0x54, 0xa2, 0x1b, 0xc4, 0x65, 0x66, 0x55, 0x21, 0xed, 0x53, 0x52, 0x49, - 0x58, 0x13, 0xd6, 0x73, 0x5b, 0x6f, 0x4d, 0x19, 0xe5, 0x1d, 0x59, 0xcc, 0x31, 0x4c, 0xad, 0x4e, - 0xbc, 0xbe, 0x6b, 0x8e, 0x7c, 0xc7, 0xe5, 0xc8, 0x81, 0x2a, 0xbe, 0x06, 0x59, 0xd3, 0x36, 0xc8, - 0x89, 0x66, 0x1a, 0x27, 0xa5, 0xc4, 0x9a, 0xb0, 0x5e, 0xe0, 0xfc, 0x0c, 0x23, 0x37, 0x8d, 0x13, - 0xbc, 0x0a, 0x4b, 0x2e, 0x79, 0x48, 0x5c, 0x8f, 0x30, 0xd3, 0x32, 0xa1, 0x69, 0x9c, 0x88, 0x25, - 0x48, 0x53, 0xff, 0x7a, 0xa5, 0x14, 0xf3, 0xcd, 0x8d, 0xd9, 0xbe, 0x99, 0x58, 0x80, 0x6e, 0x87, - 0x96, 0x30, 0x6d, 0xfc, 0x06, 0x80, 0x65, 0x0e, 0x4d, 0x5f, 0x3b, 0x34, 0x6d, 0xbf, 0x94, 0x5e, - 0x13, 0xd6, 0x93, 0x5c, 0x20, 0xcb, 0xe8, 0xb7, 0x4d, 0xdb, 0xa7, 0x7e, 0x32, 0x3d, 0xad, 0x7f, - 0x48, 0xfa, 0x0f, 0x4a, 0x8b, 0x71, 0x63, 0x4c, 0xaf, 0x46, 0x89, 0x58, 0x06, 0x78, 0x68, 0x7a, - 0xe6, 0xbe, 0x69, 0x99, 0xfe, 0x69, 0x69, 0x69, 0x4d, 0x58, 0x2f, 0x6e, 0xad, 0xcf, 0xb6, 0xa8, - 0xd3, 0xd7, 0xed, 0xbd, 0x48, 0x9e, 0x83, 0xc5, 0x10, 0xf0, 0x87, 0x70, 0x65, 0xa8, 0x9f, 0x68, - 0xbe, 0x39, 0x24, 0x9e, 0xaf, 0x0f, 0x47, 0x9a, 0x3e, 0x20, 0x9a, 0xad, 0xdb, 0x8e, 0x57, 0xca, - 0xc6, 0xe2, 0xb4, 0x32, 0xd4, 0x4f, 0xba, 0xa1, 0x8c, 0x38, 0x20, 0x32, 0x95, 0xc0, 0x9f, 0x02, - 0xe2, 0x79, 0xaf, 0x79, 0xbe, 0x4b, 0xec, 0x81, 0x7f, 0x58, 0x02, 0x66, 0xd2, 0xcd, 0x19, 0xb1, - 0xa2, 0xf6, 0xb4, 0x02, 0x95, 0x0e, 0xd7, 0xe0, 0x33, 0x2c, 0x5b, 0x93, 0x64, 0xbc, 0x0f, 0x97, - 0x43, 0xf0, 0x63, 0xdd, 0xf4, 0xb5, 0x91, 0x63, 0x99, 0xfd, 0xd3, 0x52, 0x8e, 0xe1, 0xdf, 0xfa, - 0xef, 0xf8, 0xf7, 0x74, 0xd3, 0x6f, 0x33, 0x1d, 0x3e, 0xc3, 0x25, 0x6b, 0x9a, 0x81, 0xdf, 0x82, - 0xdc, 0x48, 0x77, 0x75, 0xcb, 0x22, 0x96, 0xf9, 0x05, 0x29, 0xe5, 0x63, 0x1e, 0x8f, 0x33, 0xb0, - 0x0c, 0x45, 0xef, 0xd4, 0xf3, 0xc9, 0x50, 0x0b, 0xf7, 0x49, 0x61, 0x2d, 0xb9, 0x5e, 0xdc, 0xba, - 0x3e, 0xcb, 0x0c, 0x26, 0x5c, 0x63, 0xb2, 0x77, 0x4c, 0xdb, 0x50, 0x0b, 0x5e, 0x8c, 0xe2, 0xed, - 0xa4, 0x32, 0x19, 0x94, 0xad, 0xfc, 0x3b, 0x09, 0xa5, 0x26, 0xcd, 0xc2, 0xce, 0x03, 0x73, 0xf4, - 0x92, 0x92, 0x3f, 0x4a, 0xee, 0xe4, 0x0b, 0x25, 0xf7, 0x64, 0x5a, 0xa6, 0x5e, 0x38, 0x2d, 0x63, - 0x7b, 0x32, 0x7d, 0xde, 0x9e, 0x3c, 0x2f, 0xf3, 0x16, 0xbf, 0xe7, 0xcc, 0x5b, 0xba, 0xc0, 0xcc, - 0xab, 0x7c, 0x97, 0x86, 0xe2, 0x8e, 0x63, 0xda, 0x3f, 0x7c, 0xc4, 0x6f, 0x40, 0xd1, 0x72, 0x9c, - 0x07, 0xe3, 0x51, 0x94, 0xcb, 0x34, 0xf4, 0x85, 0x6a, 0x02, 0x09, 0x6a, 0x21, 0xe0, 0xf0, 0x34, - 0xa5, 0xe7, 0x82, 0x13, 0x9c, 0x2b, 0x2c, 0xa4, 0xb9, 0xad, 0x37, 0x67, 0x87, 0x54, 0x8a, 0x4e, - 0x1f, 0x3e, 0xe3, 0xa2, 0x63, 0x53, 0x1a, 0x7e, 0x1f, 0x52, 0xf4, 0x0c, 0xe4, 0xe1, 0xb9, 0x3a, - 0x63, 0x55, 0xd4, 0x17, 0xdd, 0xd3, 0x11, 0xe1, 0xca, 0x4c, 0xe5, 0xc2, 0x8b, 0xdd, 0xfb, 0xf0, - 0xea, 0xe4, 0xd2, 0x35, 0xdd, 0x25, 0xda, 0x03, 0x72, 0x5a, 0xca, 0xc4, 0x92, 0xec, 0xf2, 0x84, - 0x13, 0x44, 0x97, 0xdc, 0x21, 0xa7, 0xe7, 0x26, 0x5c, 0xf6, 0x7b, 0x4e, 0x38, 0xb8, 0xc8, 0x52, - 0xf7, 0x2e, 0x5c, 0x1a, 0xea, 0xa6, 0xed, 0xeb, 0xa6, 0xad, 0x39, 0xae, 0x41, 0x5c, 0xd3, 0x1e, - 0xb0, 0x62, 0x1a, 0x2e, 0x1b, 0x85, 0x6c, 0x85, 0x73, 0xcf, 0xa9, 0x7a, 0xf9, 0x17, 0xac, 0x7a, - 0x69, 0xb4, 0x48, 0xfb, 0x0f, 0xe8, 0x38, 0xae, 0xcf, 0xb3, 0xfe, 0x2e, 0x2c, 0x3b, 0x63, 0x7f, - 0x34, 0xf6, 0xcf, 0xac, 0x0a, 0xf2, 0xbf, 0x32, 0x3b, 0xd0, 0xa1, 0x85, 0xdc, 0xf2, 0x62, 0x00, - 0x10, 0xd9, 0xbd, 0x05, 0x38, 0xc4, 0xd2, 0x86, 0xba, 0xdf, 0x3f, 0xd4, 0x2c, 0x62, 0x4f, 0xec, - 0x06, 0x14, 0xf2, 0x77, 0x29, 0xbb, 0x45, 0xec, 0xca, 0x57, 0x02, 0xe4, 0xeb, 0xa6, 0xe7, 0x9b, - 0x76, 0xdf, 0x67, 0x76, 0x5d, 0x87, 0x65, 0x26, 0x44, 0x0c, 0x2d, 0xde, 0x1b, 0x15, 0xd4, 0x22, - 0x27, 0x87, 0x9b, 0xe4, 0x06, 0x20, 0x83, 0x2b, 0x46, 0x92, 0x09, 0x26, 0xb9, 0x1c, 0xd2, 0x43, - 0xd1, 0x2d, 0xc0, 0xf6, 0xd8, 0xb2, 0x82, 0xb4, 0x0b, 0x99, 0x13, 0x4d, 0x07, 0x62, 0x7c, 0xd1, - 0x25, 0xa1, 0x2d, 0xf8, 0x2d, 0xc8, 0x13, 0xd7, 0x75, 0x5c, 0xcd, 0xb1, 0x35, 0x63, 0x3c, 0x62, - 0x1b, 0x31, 0x1b, 0xe6, 0x36, 0xe3, 0x28, 0x76, 0x7d, 0x3c, 0xaa, 0x20, 0x28, 0x2a, 0xae, 0x61, - 0xda, 0x3a, 0xcd, 0x74, 0xba, 0x82, 0xca, 0x6f, 0x92, 0x80, 0x3e, 0x31, 0x07, 0x5f, 0xe8, 0x03, - 0xba, 0xb9, 0xb8, 0xbb, 0xeb, 0xb0, 0xc8, 0x2a, 0x45, 0xd8, 0xe9, 0xcd, 0x57, 0x65, 0xb8, 0x2e, - 0x6e, 0x00, 0x90, 0xa3, 0x89, 0xd5, 0xe6, 0xb6, 0xae, 0xcd, 0x8e, 0x17, 0x5f, 0x7f, 0xd8, 0xee, - 0x90, 0xa3, 0x33, 0xdf, 0x15, 0x83, 0x72, 0xe5, 0x04, 0xa6, 0x4f, 0xd4, 0x22, 0xc6, 0xe1, 0x6b, - 0xba, 0xa0, 0x5a, 0x74, 0x07, 0xf2, 0x07, 0xe6, 0x09, 0x31, 0xb4, 0x87, 0xac, 0x01, 0x2e, 0xa5, - 0x99, 0xe5, 0x4f, 0x29, 0x29, 0x93, 0x8d, 0xb2, 0x9a, 0x63, 0xda, 0x01, 0xf1, 0x05, 0x0a, 0x5b, - 0xe5, 0xaf, 0x49, 0x58, 0xde, 0x25, 0xee, 0x80, 0xc4, 0x22, 0xb3, 0x0b, 0x05, 0x8b, 0x1c, 0xbc, - 0xc0, 0x36, 0xc8, 0x53, 0xf5, 0x68, 0x13, 0x28, 0x50, 0x74, 0xcd, 0xc1, 0x61, 0x0c, 0x2f, 0x31, - 0x27, 0x5e, 0x81, 0xe9, 0x47, 0x80, 0xb1, 0x00, 0xa4, 0x5f, 0xc6, 0x61, 0x70, 0x03, 0x0a, 0x74, - 0x73, 0x68, 0xe4, 0x68, 0xac, 0x47, 0xe7, 0x41, 0xb8, 0x6f, 0xf2, 0x94, 0x25, 0x71, 0x0e, 0xfe, - 0x00, 0xae, 0x30, 0x57, 0x9e, 0xe5, 0xe8, 0x8c, 0x42, 0x4f, 0x0e, 0x7c, 0xe9, 0x68, 0xb2, 0xd0, - 0xff, 0x1c, 0x4a, 0x81, 0xdf, 0xce, 0x51, 0xce, 0xc6, 0x94, 0x57, 0x98, 0xd4, 0x94, 0x76, 0xe5, - 0x57, 0x49, 0x28, 0xde, 0xd6, 0xbd, 0xc3, 0x58, 0x5c, 0x6f, 0xc2, 0xf2, 0x94, 0x31, 0x41, 0x21, - 0xe1, 0x07, 0x6e, 0xdc, 0x04, 0x7c, 0x0b, 0xd0, 0xf4, 0xe4, 0x41, 0x2d, 0x61, 0xc2, 0xc5, 0xc9, - 0x29, 0x5f, 0x7a, 0x44, 0xde, 0x86, 0xe2, 0x90, 0x26, 0xf1, 0x59, 0x85, 0x8c, 0x87, 0xa4, 0x10, - 0xf0, 0x42, 0x63, 0x5f, 0x5e, 0x4c, 0xfe, 0x92, 0x00, 0xdc, 0xe4, 0xb7, 0xe5, 0x58, 0x5c, 0x7e, - 0xa0, 0x76, 0x4b, 0x81, 0x42, 0x78, 0x55, 0x7f, 0xde, 0xea, 0x95, 0x0f, 0x01, 0x58, 0xc0, 0x5e, - 0x72, 0xd4, 0x77, 0x52, 0x99, 0x24, 0x4a, 0x55, 0x7e, 0x2f, 0xc0, 0x4a, 0xe8, 0xd4, 0x86, 0x69, - 0xf9, 0xc4, 0xe5, 0x6e, 0xdd, 0x00, 0x14, 0xad, 0xb7, 0xef, 0x58, 0xcc, 0x33, 0x42, 0xcc, 0x33, - 0xc5, 0x90, 0x5b, 0x73, 0x2c, 0xea, 0x9f, 0xcf, 0xa6, 0xfd, 0x13, 0x94, 0xa9, 0x9f, 0x4c, 0x99, - 0xe4, 0x8c, 0xfc, 0x8d, 0xf8, 0x93, 0xc7, 0x06, 0xbd, 0x83, 0x9c, 0x2d, 0xaf, 0xed, 0x3a, 0xbe, - 0x73, 0x9e, 0xbb, 0x2a, 0x7f, 0xc8, 0x40, 0x51, 0x1c, 0x0c, 0x5c, 0x32, 0xd0, 0x7d, 0x27, 0x30, - 0xf1, 0x1a, 0xc0, 0xc0, 0x75, 0x82, 0x2e, 0x30, 0xbe, 0xbf, 0xb2, 0x8c, 0x5a, 0x73, 0x2c, 0x0f, - 0x7f, 0x06, 0x79, 0x9d, 0x2b, 0x99, 0x4e, 0x74, 0x3b, 0xfa, 0xe9, 0x6c, 0x4f, 0x4f, 0x4e, 0x11, - 0x0d, 0x63, 0x41, 0x8c, 0xe3, 0xe1, 0x1f, 0xf3, 0x16, 0x85, 0x18, 0x5a, 0xcc, 0x94, 0x54, 0x64, - 0x0a, 0xe2, 0xdc, 0xed, 0xc8, 0xa2, 0x6d, 0x1e, 0xb1, 0x34, 0x8b, 0xd8, 0x3b, 0xcf, 0x6c, 0xc9, - 0x74, 0xfc, 0xca, 0xbf, 0x48, 0x40, 0x2e, 0x66, 0x1e, 0x05, 0x3e, 0x18, 0xdb, 0x7d, 0x16, 0xa4, - 0x79, 0x80, 0x1b, 0x63, 0xbb, 0x1f, 0x02, 0x53, 0x00, 0xbc, 0x06, 0x99, 0xa8, 0xa7, 0x49, 0xc4, - 0x76, 0x65, 0x44, 0xc5, 0x6f, 0x42, 0xf1, 0x80, 0xe5, 0x4a, 0x94, 0x19, 0x74, 0x33, 0x14, 0xd4, - 0x7c, 0x40, 0xe5, 0x19, 0x71, 0x85, 0xbd, 0x46, 0x31, 0x76, 0x9a, 0xf5, 0x51, 0x8b, 0xfd, 0x80, - 0x71, 0x1b, 0xb2, 0xba, 0x3b, 0x18, 0x0f, 0x89, 0xed, 0x7b, 0xa5, 0x45, 0x16, 0x91, 0x79, 0x72, - 0xff, 0x4c, 0x99, 0xe7, 0xf0, 0x3f, 0x93, 0x90, 0xa2, 0xab, 0xc0, 0x08, 0xf2, 0xa2, 0xfc, 0xb1, - 0x26, 0x2b, 0x5d, 0x4d, 0xee, 0xb5, 0x5a, 0x68, 0x01, 0x2f, 0x41, 0x52, 0xdc, 0xdb, 0x46, 0x02, - 0xce, 0x43, 0xa6, 0xaa, 0x28, 0x2d, 0x4d, 0x94, 0xeb, 0x28, 0x81, 0x73, 0xb0, 0xc4, 0x46, 0x8a, - 0x8a, 0x92, 0xb8, 0x08, 0x50, 0x53, 0xe4, 0x9a, 0xd8, 0xd5, 0xc4, 0xed, 0x6d, 0x94, 0xc2, 0x59, - 0x48, 0xd7, 0x94, 0x9e, 0xdc, 0x45, 0x69, 0xaa, 0xbe, 0x2b, 0xde, 0x47, 0x4b, 0xec, 0x47, 0x53, - 0x46, 0x19, 0x0c, 0xb0, 0xd8, 0xe9, 0xd6, 0xeb, 0xd2, 0x1e, 0xca, 0x52, 0x62, 0xa7, 0xb7, 0x8b, - 0x80, 0xc2, 0x75, 0x7a, 0xbb, 0x5a, 0x53, 0xee, 0xa2, 0x1c, 0x9d, 0x69, 0x4f, 0x54, 0x9b, 0xa2, - 0x5c, 0x93, 0x50, 0x9e, 0xb2, 0xee, 0x2b, 0x2a, 0x43, 0x2e, 0x04, 0x33, 0xf5, 0xe4, 0xae, 0xa6, - 0x2a, 0xf7, 0x3a, 0xa8, 0xc8, 0xf4, 0xee, 0xaa, 0xf5, 0x66, 0xa3, 0x81, 0x96, 0x31, 0x86, 0x62, - 0xa3, 0x29, 0x8b, 0x2d, 0x2d, 0xd2, 0x46, 0x74, 0x41, 0x01, 0x8d, 0xcf, 0x79, 0x09, 0x17, 0x20, - 0x2b, 0xaa, 0xaa, 0xf8, 0x31, 0x43, 0xc4, 0x74, 0xb2, 0x9d, 0x8e, 0x22, 0xb3, 0xd1, 0x65, 0xca, - 0xa4, 0xa3, 0x2a, 0x1b, 0xae, 0xd0, 0xe9, 0x3a, 0x5d, 0xb5, 0x29, 0x6f, 0xb3, 0xf1, 0x2b, 0x6c, - 0xd5, 0xcd, 0x2e, 0x73, 0xc1, 0xab, 0x74, 0x21, 0x74, 0xa0, 0xa8, 0xe8, 0x0a, 0xce, 0x40, 0xaa, - 0xa6, 0xa8, 0x2a, 0x2a, 0xe1, 0x12, 0xac, 0xb4, 0x25, 0xb5, 0x26, 0xc9, 0xdd, 0x66, 0x4b, 0xd2, - 0xea, 0xcd, 0x4e, 0x4d, 0x6b, 0xee, 0xb6, 0x5b, 0xe8, 0xb5, 0x29, 0x4e, 0x4d, 0x91, 0xbb, 0x01, - 0xa7, 0x8c, 0x2f, 0xc3, 0x32, 0xb3, 0x41, 0xa9, 0xee, 0x48, 0xb5, 0xc0, 0x89, 0xaf, 0xe3, 0x15, - 0x40, 0x81, 0x29, 0x31, 0xea, 0xff, 0x51, 0x0b, 0xf6, 0x44, 0x55, 0x6b, 0x2b, 0x6d, 0xf4, 0xff, - 0x81, 0x79, 0x74, 0x59, 0x6c, 0xbc, 0x8a, 0x97, 0x21, 0xd7, 0xe9, 0x6a, 0xbb, 0xe2, 0x1d, 0xa9, - 0xd5, 0x94, 0x25, 0x74, 0x95, 0x2e, 0xa7, 0xd3, 0xd5, 0xa4, 0xfb, 0x5d, 0x49, 0xee, 0xa2, 0xb5, - 0xca, 0x2d, 0x48, 0xd1, 0x4d, 0x40, 0xad, 0x15, 0x7b, 0x5d, 0x05, 0x2d, 0xb0, 0x60, 0xd4, 0xc4, - 0x96, 0xa8, 0x22, 0x81, 0xa2, 0xc9, 0x8a, 0xac, 0xf1, 0x71, 0xa2, 0xf2, 0xa7, 0x45, 0x78, 0xbd, - 0x69, 0xfb, 0xc4, 0xb5, 0x88, 0xfe, 0x90, 0x18, 0xc1, 0xfd, 0x3c, 0x76, 0x6c, 0x7c, 0x3c, 0xd5, - 0x40, 0x7f, 0x38, 0x3b, 0x03, 0x9f, 0x02, 0x13, 0x1c, 0x2b, 0x53, 0x5d, 0x75, 0xec, 0xd1, 0x23, - 0x71, 0xde, 0xa3, 0xc7, 0xe4, 0x0b, 0x62, 0xf2, 0xfc, 0x17, 0xc4, 0x0b, 0xbd, 0xb3, 0xa7, 0xe7, - 0x6f, 0x0a, 0xfe, 0xd7, 0x5f, 0x66, 0xca, 0x5f, 0x25, 0x20, 0xcd, 0xa2, 0x83, 0x3f, 0x82, 0x94, - 0x41, 0xbc, 0xfe, 0x73, 0x35, 0x08, 0x4c, 0xf3, 0x59, 0xfa, 0x83, 0x1a, 0xa4, 0x46, 0x8e, 0x17, - 0x84, 0xf3, 0xa9, 0xef, 0x6f, 0x6d, 0xc7, 0xf3, 0xdb, 0xc1, 0x37, 0x01, 0x9a, 0x41, 0xe1, 0x3c, - 0x54, 0x19, 0xd7, 0x21, 0x13, 0xb5, 0xf9, 0xa9, 0x39, 0xdb, 0xfc, 0x48, 0xf3, 0xec, 0x2d, 0x30, - 0xfd, 0x22, 0x6f, 0x81, 0x95, 0x3f, 0x0b, 0x50, 0x6c, 0xbb, 0xce, 0xe7, 0xa4, 0xef, 0x77, 0x48, - 0x70, 0x99, 0xfe, 0x08, 0xd2, 0x34, 0x23, 0xc3, 0x3d, 0x33, 0x4f, 0x4a, 0x06, 0x8a, 0x78, 0x1b, - 0x2e, 0x0d, 0x88, 0x4d, 0x5c, 0xdd, 0x8f, 0xb5, 0x9b, 0xc1, 0xc5, 0xb3, 0x3c, 0x1d, 0x18, 0x32, - 0xdc, 0x08, 0xbe, 0xba, 0x74, 0x55, 0x14, 0x29, 0x85, 0x7d, 0xe8, 0x75, 0x40, 0xf6, 0x98, 0xbd, - 0x68, 0x78, 0xda, 0x88, 0xb8, 0xda, 0x80, 0xd8, 0xc1, 0xa5, 0x53, 0x2d, 0xd8, 0xe3, 0x21, 0x3d, - 0x6a, 0xdb, 0xc4, 0xdd, 0x26, 0x76, 0xe5, 0xdb, 0x02, 0xe4, 0xef, 0x99, 0xb6, 0xe1, 0x1c, 0xf3, - 0x9d, 0xbf, 0xc6, 0x1e, 0x8b, 0x7d, 0x93, 0x1d, 0xea, 0xa7, 0xfc, 0x35, 0x20, 0x4e, 0xc2, 0x1d, - 0xc8, 0x1e, 0x33, 0x8d, 0x46, 0x64, 0xdc, 0xe6, 0xec, 0xa5, 0xc6, 0xc1, 0xf9, 0xa0, 0x11, 0x9d, - 0x55, 0x11, 0x4e, 0xf9, 0x8f, 0x02, 0x3f, 0xa5, 0x3a, 0x50, 0x08, 0x7b, 0x08, 0xd2, 0x78, 0xde, - 0x13, 0x5b, 0x9d, 0xc4, 0xc0, 0x77, 0x01, 0xf8, 0x54, 0x14, 0x31, 0xc1, 0x10, 0xdf, 0x9d, 0xcf, - 0x66, 0x8a, 0x1a, 0x03, 0xf9, 0x20, 0xf5, 0xe8, 0xcb, 0xab, 0x42, 0xf9, 0xcb, 0x25, 0x48, 0x37, - 0x5c, 0x7d, 0x48, 0xf0, 0x1d, 0x48, 0x0d, 0x1d, 0x83, 0x70, 0x73, 0x9f, 0x15, 0x9c, 0xe9, 0x6e, - 0xec, 0x3a, 0x46, 0x54, 0x5e, 0x28, 0x08, 0xbe, 0x0b, 0x8b, 0xfb, 0xce, 0xd8, 0x36, 0xbc, 0x19, - 0x7d, 0xe2, 0xd3, 0xe1, 0xaa, 0x4c, 0x35, 0x2c, 0x76, 0x01, 0x10, 0xfe, 0x04, 0xb2, 0xe4, 0xa4, - 0x6f, 0x8d, 0x69, 0xd2, 0xb1, 0x6d, 0x58, 0xdc, 0x7a, 0x6f, 0x2e, 0x54, 0x29, 0xd4, 0x8e, 0x1e, - 0x38, 0x42, 0x42, 0xf9, 0x3b, 0x01, 0xd2, 0x6c, 0x52, 0x3a, 0x0b, 0x9b, 0x8f, 0x16, 0x4c, 0xee, - 0x8a, 0xf7, 0xe6, 0xb7, 0x3d, 0x56, 0x6e, 0xcf, 0xe0, 0xe8, 0xc1, 0x60, 0xda, 0xbe, 0xe6, 0x1c, - 0x1c, 0x78, 0x24, 0xe8, 0xbd, 0xc2, 0xef, 0x36, 0x59, 0xd3, 0xf6, 0x15, 0x46, 0xc6, 0xd7, 0x20, - 0x4f, 0x77, 0x85, 0x11, 0x8a, 0xd1, 0x95, 0xe6, 0xd5, 0x1c, 0xa3, 0x71, 0x91, 0x1d, 0xc8, 0x05, - 0x4c, 0xf6, 0xb5, 0x93, 0x57, 0x92, 0x39, 0xbe, 0x05, 0x42, 0xa0, 0x4d, 0x6d, 0x2a, 0xff, 0x56, - 0x80, 0xc5, 0xc0, 0xdd, 0x58, 0x86, 0xb4, 0xe7, 0xeb, 0xae, 0xcf, 0x0b, 0xe9, 0xd6, 0xfc, 0xcb, - 0x8e, 0x0a, 0x0c, 0x85, 0xc1, 0x75, 0x48, 0x12, 0xdb, 0xe0, 0x09, 0xf0, 0x1c, 0x68, 0x2a, 0x55, - 0xaf, 0x5c, 0x87, 0x14, 0xcd, 0x2e, 0xda, 0xb6, 0xa9, 0xa2, 0xbc, 0x2d, 0xa1, 0x05, 0xda, 0x21, - 0xb0, 0x0e, 0x4b, 0xa0, 0x1d, 0xc2, 0xb6, 0xaa, 0xf4, 0xda, 0x1d, 0x94, 0xa8, 0x7c, 0x01, 0xd9, - 0xc8, 0xf7, 0xf8, 0x0a, 0x5c, 0xee, 0xc9, 0x55, 0xa5, 0x27, 0xd7, 0xa5, 0xba, 0xd6, 0x56, 0xa5, - 0x9a, 0x54, 0x6f, 0xca, 0xdb, 0x68, 0x61, 0x92, 0xd1, 0x50, 0x5a, 0x2d, 0xe5, 0x1e, 0x65, 0x08, - 0xb4, 0xa3, 0x51, 0x1a, 0x8d, 0x8e, 0xd4, 0x8d, 0x89, 0x27, 0x62, 0xd4, 0x33, 0xd9, 0x24, 0x6d, - 0x65, 0x6a, 0x3d, 0x55, 0x95, 0x82, 0x56, 0x0f, 0xa5, 0x2a, 0x9f, 0x42, 0x36, 0xca, 0x2e, 0xda, - 0xd5, 0xc9, 0x8a, 0x26, 0xdd, 0xaf, 0xb5, 0x7a, 0x9d, 0xa6, 0x22, 0x07, 0x93, 0xb2, 0x61, 0x5d, - 0xd2, 0xe2, 0x7a, 0x02, 0xbe, 0x04, 0x85, 0x90, 0xc1, 0xd6, 0x81, 0x12, 0x54, 0x3b, 0x24, 0x75, - 0x9b, 0x52, 0x07, 0x25, 0xcb, 0x7f, 0x4b, 0x40, 0x26, 0xac, 0x3b, 0x58, 0x8a, 0x5d, 0x03, 0x72, - 0x5b, 0x6f, 0x3f, 0xab, 0x57, 0xa7, 0x2f, 0x01, 0x17, 0x73, 0x12, 0x55, 0x21, 0x7d, 0x40, 0xe3, - 0xc5, 0x6f, 0xb8, 0xb7, 0xe6, 0x89, 0xb1, 0x1a, 0xa8, 0xe2, 0x75, 0x98, 0xb8, 0x56, 0xb0, 0x26, - 0x24, 0x1d, 0x5e, 0xc6, 0x26, 0x2e, 0x1c, 0x65, 0xc8, 0xe8, 0xee, 0xc0, 0x6b, 0x1a, 0x27, 0x5e, - 0x69, 0x89, 0x55, 0xf5, 0x68, 0x4c, 0x51, 0x82, 0xd7, 0x65, 0x8e, 0x92, 0x89, 0x1d, 0xe2, 0x13, - 0x9c, 0x9d, 0x54, 0x26, 0x81, 0x92, 0xfc, 0x66, 0xf1, 0x3b, 0x01, 0xe0, 0xac, 0x3a, 0xd2, 0x1e, - 0x53, 0x55, 0xee, 0x69, 0x72, 0x6f, 0xb7, 0x2a, 0xa9, 0x3c, 0xcf, 0x44, 0xf9, 0x4e, 0xd0, 0x7d, - 0xd6, 0x25, 0xb9, 0x23, 0x69, 0x6c, 0xcc, 0x82, 0xc4, 0xbb, 0xe5, 0x80, 0x92, 0xa4, 0xcd, 0x6c, - 0xad, 0xb7, 0xcb, 0x7a, 0xea, 0x6e, 0x70, 0xc9, 0x60, 0x9d, 0x74, 0x70, 0xc9, 0x68, 0x89, 0xdb, - 0x68, 0x91, 0xc2, 0xb5, 0x24, 0xb1, 0x8e, 0x96, 0x68, 0xfe, 0x34, 0x9a, 0x6a, 0xa7, 0xab, 0xed, - 0x89, 0xad, 0x9e, 0x84, 0x32, 0x14, 0xbf, 0x25, 0x46, 0xe3, 0x2c, 0x45, 0x93, 0xbb, 0xb7, 0xf9, - 0x10, 0x6e, 0xfe, 0x0c, 0x8a, 0x93, 0x1f, 0x4d, 0x68, 0xe2, 0xb7, 0x7b, 0xd5, 0x56, 0xb3, 0x86, - 0x16, 0xf0, 0x6b, 0xf0, 0x4a, 0xf0, 0x9b, 0xb6, 0xfe, 0xec, 0x76, 0xc4, 0x59, 0x42, 0xf5, 0x9d, - 0x47, 0xdf, 0xae, 0x2e, 0x3c, 0x7a, 0xbc, 0x2a, 0x7c, 0xfd, 0x78, 0x55, 0xf8, 0xe6, 0xf1, 0xaa, - 0xf0, 0x8f, 0xc7, 0xab, 0xc2, 0x2f, 0x9f, 0xac, 0x2e, 0x7c, 0xfd, 0x64, 0x75, 0xe1, 0x9b, 0x27, - 0xab, 0x0b, 0x9f, 0xe4, 0x62, 0xff, 0xcb, 0xf0, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x93, 0x56, - 0x71, 0x9c, 0xbb, 0x21, 0x00, 0x00, + proto.RegisterFile("sql/execinfrapb/processors_sql.proto", fileDescriptor_processors_sql_87f40537b51e0560) +} + +var fileDescriptor_processors_sql_87f40537b51e0560 = []byte{ + // 2734 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3a, 0xcd, 0x73, 0xdb, 0xc6, + 0xf5, 0x02, 0x3f, 0x24, 0xf2, 0xf1, 0x43, 0xeb, 0xb5, 0x12, 0x33, 0xcc, 0xef, 0x27, 0xcb, 0x4c, + 0x1a, 0xcb, 0x8e, 0x23, 0x35, 0x6a, 0x27, 0x9d, 0x24, 0x3d, 0x04, 0x24, 0x41, 0x99, 0x32, 0x05, + 0xd0, 0x20, 0x29, 0x3b, 0xc9, 0x4c, 0x30, 0x10, 0xb1, 0xa2, 0x10, 0x83, 0x00, 0x05, 0x80, 0x96, + 0x94, 0x7f, 0xa0, 0xd7, 0x76, 0x7a, 0xe9, 0xa9, 0x93, 0x4b, 0xfb, 0x17, 0xf4, 0xd6, 0x99, 0xf4, + 0xd2, 0x83, 0x8f, 0x99, 0x1e, 0xda, 0x9c, 0x3a, 0x8d, 0xfd, 0x17, 0xb4, 0x97, 0x4c, 0x6f, 0x9d, + 0x5d, 0x2c, 0x20, 0x90, 0x23, 0xba, 0xa6, 0xad, 0xc4, 0xd3, 0x8b, 0x86, 0xfb, 0xbe, 0xf6, 0x7d, + 0xed, 0xdb, 0xf7, 0x16, 0x82, 0x37, 0xbd, 0x23, 0x6b, 0x93, 0x9c, 0x90, 0xbe, 0x69, 0x1f, 0xb8, + 0xfa, 0x68, 0x7f, 0x73, 0xe4, 0x3a, 0x7d, 0xe2, 0x79, 0x8e, 0xeb, 0x69, 0xde, 0x91, 0xb5, 0x31, + 0x72, 0x1d, 0xdf, 0xc1, 0xa5, 0xbe, 0xd3, 0x7f, 0xe0, 0x3a, 0x7a, 0xff, 0x70, 0x83, 0x02, 0x0d, + 0xd3, 0xf3, 0xbd, 0x23, 0xcb, 0x1d, 0xdb, 0xe5, 0x37, 0x28, 0x7f, 0x5f, 0xf7, 0x75, 0xcb, 0x19, + 0x6c, 0x1a, 0xc4, 0xeb, 0x8f, 0xf6, 0x37, 0x3d, 0xdf, 0x1d, 0xf7, 0xfd, 0xb1, 0x4b, 0x8c, 0x80, + 0xbd, 0x5c, 0x39, 0x87, 0xe8, 0x73, 0xc7, 0xb4, 0x35, 0xff, 0x74, 0x44, 0x38, 0xcd, 0xda, 0x39, + 0x34, 0x96, 0xd3, 0x7f, 0x60, 0xda, 0x03, 0x4e, 0xf1, 0x0a, 0xa5, 0xa0, 0x1c, 0x5e, 0xf0, 0x97, + 0x83, 0xcb, 0xd3, 0x16, 0x18, 0xba, 0xaf, 0x73, 0xdc, 0x8f, 0x9e, 0x62, 0xdd, 0xbe, 0xee, 0x85, + 0x7b, 0xdf, 0xa4, 0x64, 0xce, 0xc8, 0xdf, 0x34, 0xed, 0x87, 0xc4, 0xf5, 0x89, 0x41, 0x4e, 0x46, + 0xee, 0xa6, 0x37, 0xd2, 0x6d, 0x8d, 0xfe, 0x22, 0x9e, 0x67, 0x3a, 0x36, 0xa7, 0x5d, 0x19, 0x38, + 0x03, 0x87, 0xfd, 0xdc, 0xa4, 0xbf, 0x02, 0x68, 0xe5, 0xd7, 0x02, 0x14, 0xf7, 0x74, 0x6b, 0x4c, + 0xbc, 0x9a, 0xe3, 0x92, 0xce, 0x88, 0xf4, 0x71, 0x0d, 0x96, 0xfa, 0x8e, 0x35, 0x1e, 0xda, 0x5e, + 0x49, 0x58, 0x4b, 0xae, 0xe7, 0xb6, 0xde, 0xd8, 0x98, 0xe5, 0xc5, 0x8d, 0xba, 0xee, 0x8f, 0x87, + 0x4d, 0xfb, 0xc0, 0xa9, 0xa6, 0x1e, 0xfd, 0xfd, 0xea, 0x82, 0x1a, 0x72, 0xe2, 0xd7, 0x21, 0xeb, + 0xea, 0xc7, 0xda, 0xfe, 0xa9, 0x4f, 0xbc, 0x52, 0x62, 0x2d, 0xb9, 0x9e, 0x57, 0x33, 0xae, 0x7e, + 0x5c, 0xa5, 0x6b, 0x7c, 0x15, 0x32, 0xf6, 0x78, 0xa8, 0xb9, 0xce, 0xb1, 0x57, 0x4a, 0xae, 0x09, + 0xeb, 0xa9, 0x90, 0xdb, 0x1e, 0x0f, 0x55, 0xe7, 0xd8, 0xab, 0xfc, 0x33, 0x0d, 0xcb, 0x5d, 0x7d, + 0xdf, 0x22, 0x2a, 0xd1, 0x0d, 0xe2, 0x32, 0xb5, 0xaa, 0x90, 0xf6, 0x29, 0xa8, 0x24, 0xac, 0x09, + 0xeb, 0xb9, 0xad, 0xb7, 0xa6, 0x94, 0xf2, 0x8e, 0x2c, 0xe6, 0x18, 0xc6, 0x56, 0x27, 0x5e, 0xdf, + 0x35, 0x47, 0xbe, 0xe3, 0x72, 0xc9, 0x01, 0x2b, 0xbe, 0x06, 0x59, 0xd3, 0x36, 0xc8, 0x89, 0x66, + 0x1a, 0x27, 0xa5, 0xc4, 0x9a, 0xb0, 0x5e, 0xe0, 0xf8, 0x0c, 0x03, 0x37, 0x8d, 0x13, 0xbc, 0x0a, + 0x4b, 0x2e, 0x79, 0x48, 0x5c, 0x8f, 0x30, 0xd5, 0x32, 0xa1, 0x6a, 0x1c, 0x88, 0x25, 0x48, 0x53, + 0xff, 0x7a, 0xa5, 0x14, 0xf3, 0xcd, 0x8d, 0xd9, 0xbe, 0x99, 0x30, 0x40, 0xb7, 0x43, 0x4d, 0x18, + 0x37, 0x7e, 0x03, 0xc0, 0x32, 0x87, 0xa6, 0xaf, 0x1d, 0x9a, 0xb6, 0x5f, 0x4a, 0xaf, 0x09, 0xeb, + 0x49, 0x4e, 0x90, 0x65, 0xf0, 0xdb, 0xa6, 0xed, 0x53, 0x3f, 0x99, 0x9e, 0xd6, 0x3f, 0x24, 0xfd, + 0x07, 0xa5, 0xc5, 0xb8, 0x32, 0xa6, 0x57, 0xa3, 0x40, 0x2c, 0x03, 0x3c, 0x34, 0x3d, 0x73, 0xdf, + 0xb4, 0x4c, 0xff, 0xb4, 0xb4, 0xb4, 0x26, 0xac, 0x17, 0xb7, 0xd6, 0x67, 0x6b, 0xd4, 0xe9, 0xeb, + 0xf6, 0x5e, 0x44, 0xcf, 0x85, 0xc5, 0x24, 0xe0, 0x0f, 0xe1, 0xca, 0x50, 0x3f, 0xd1, 0x7c, 0x73, + 0x48, 0x3c, 0x5f, 0x1f, 0x8e, 0x34, 0x7d, 0x40, 0x34, 0x5b, 0xb7, 0x1d, 0xaf, 0x94, 0x8d, 0xc5, + 0x69, 0x65, 0xa8, 0x9f, 0x74, 0x43, 0x1a, 0x71, 0x40, 0x64, 0x4a, 0x81, 0x3f, 0x05, 0xc4, 0xf3, + 0x5e, 0xf3, 0x7c, 0x97, 0xd8, 0x03, 0xff, 0xb0, 0x04, 0x4c, 0xa5, 0x9b, 0x33, 0x62, 0x45, 0xf5, + 0x69, 0x05, 0x2c, 0x1d, 0xce, 0xc1, 0x77, 0x58, 0xb6, 0x26, 0xc1, 0x78, 0x1f, 0x2e, 0x87, 0xc2, + 0x8f, 0x75, 0xd3, 0xd7, 0x46, 0x8e, 0x65, 0xf6, 0x4f, 0x4b, 0x39, 0x26, 0xff, 0xd6, 0x7f, 0x97, + 0x7f, 0x4f, 0x37, 0xfd, 0x36, 0xe3, 0xe1, 0x3b, 0x5c, 0xb2, 0xa6, 0x11, 0xf8, 0x2d, 0xc8, 0x8d, + 0x74, 0x57, 0xb7, 0x2c, 0x62, 0x99, 0x5f, 0x90, 0x52, 0x3e, 0xe6, 0xf1, 0x38, 0x02, 0xcb, 0x50, + 0xf4, 0x4e, 0x3d, 0x9f, 0x0c, 0xb5, 0xf0, 0x9c, 0x14, 0xd6, 0x92, 0xeb, 0xc5, 0xad, 0xeb, 0xb3, + 0xd4, 0x60, 0xc4, 0x35, 0x46, 0x7b, 0xc7, 0xb4, 0x0d, 0xb5, 0xe0, 0xc5, 0x20, 0xde, 0x4e, 0x2a, + 0x93, 0x41, 0xd9, 0xca, 0xbf, 0x93, 0x50, 0x6a, 0xd2, 0x2c, 0xec, 0x3c, 0x30, 0x47, 0x2f, 0x29, + 0xf9, 0xa3, 0xe4, 0x4e, 0xbe, 0x50, 0x72, 0x4f, 0xa6, 0x65, 0xea, 0x85, 0xd3, 0x32, 0x76, 0x26, + 0xd3, 0xe7, 0x9d, 0xc9, 0xf3, 0x32, 0x6f, 0xf1, 0x7b, 0xce, 0xbc, 0xa5, 0x0b, 0xcc, 0xbc, 0xca, + 0x77, 0x69, 0x28, 0xee, 0x38, 0xa6, 0xfd, 0xc3, 0x47, 0xfc, 0x06, 0x14, 0x2d, 0xc7, 0x79, 0x30, + 0x1e, 0x45, 0xb9, 0x4c, 0x43, 0x5f, 0xa8, 0x26, 0x90, 0xa0, 0x16, 0x02, 0x0c, 0x4f, 0x53, 0x7a, + 0x2f, 0x38, 0xc1, 0xbd, 0xc2, 0x42, 0x9a, 0xdb, 0x7a, 0x73, 0x76, 0x48, 0xa5, 0xe8, 0xf6, 0xe1, + 0x3b, 0x2e, 0x3a, 0x36, 0x85, 0xe1, 0xf7, 0x21, 0x45, 0xef, 0x40, 0x1e, 0x9e, 0xab, 0x33, 0xac, + 0xa2, 0xbe, 0xe8, 0x9e, 0x8e, 0x08, 0x67, 0x66, 0x2c, 0x17, 0x5e, 0xec, 0xde, 0x87, 0x57, 0x27, + 0x4d, 0xd7, 0x74, 0x97, 0x68, 0x0f, 0xc8, 0x69, 0x29, 0x13, 0x4b, 0xb2, 0xcb, 0x13, 0x4e, 0x10, + 0x5d, 0x72, 0x87, 0x9c, 0x9e, 0x9b, 0x70, 0xd9, 0xef, 0x39, 0xe1, 0xe0, 0x22, 0x4b, 0xdd, 0xbb, + 0x70, 0x69, 0xa8, 0x9b, 0xb6, 0xaf, 0x9b, 0xb6, 0xe6, 0xb8, 0x06, 0x71, 0x4d, 0x7b, 0xc0, 0x8a, + 0x69, 0x68, 0x36, 0x0a, 0xd1, 0x0a, 0xc7, 0x9e, 0x53, 0xf5, 0xf2, 0x2f, 0x58, 0xf5, 0xd2, 0x68, + 0x91, 0xf6, 0x1f, 0xd0, 0x71, 0x5c, 0x9f, 0x67, 0xfd, 0x5d, 0x58, 0x76, 0xc6, 0xfe, 0x68, 0xec, + 0x9f, 0x69, 0x15, 0xe4, 0x7f, 0x65, 0x76, 0xa0, 0x43, 0x0d, 0xb9, 0xe6, 0xc5, 0x40, 0x40, 0xa4, + 0xf7, 0x16, 0xe0, 0x50, 0x96, 0x36, 0xd4, 0xfd, 0xfe, 0xa1, 0x66, 0x11, 0x7b, 0xe2, 0x34, 0xa0, + 0x10, 0xbf, 0x4b, 0xd1, 0x2d, 0x62, 0x57, 0xbe, 0x12, 0x20, 0x5f, 0x37, 0x3d, 0xdf, 0xb4, 0xfb, + 0x3e, 0xd3, 0xeb, 0x3a, 0x2c, 0x33, 0x22, 0x62, 0x68, 0xf1, 0xde, 0xa8, 0xa0, 0x16, 0x39, 0x38, + 0x3c, 0x24, 0x37, 0x00, 0x19, 0x9c, 0x31, 0xa2, 0x4c, 0x30, 0xca, 0xe5, 0x10, 0x1e, 0x92, 0x6e, + 0x01, 0xb6, 0xc7, 0x96, 0x15, 0xa4, 0x5d, 0x88, 0x9c, 0x68, 0x3a, 0x10, 0xc3, 0x8b, 0x2e, 0x09, + 0x75, 0xc1, 0x6f, 0x41, 0x9e, 0xb8, 0xae, 0xe3, 0x6a, 0x8e, 0xad, 0x19, 0xe3, 0x11, 0x3b, 0x88, + 0xd9, 0x30, 0xb7, 0x19, 0x46, 0xb1, 0xeb, 0xe3, 0x51, 0x05, 0x41, 0x51, 0x71, 0x0d, 0xd3, 0xd6, + 0x69, 0xa6, 0x53, 0x0b, 0x2a, 0xbf, 0x49, 0x02, 0xfa, 0xc4, 0x1c, 0x7c, 0xa1, 0x0f, 0xe8, 0xe1, + 0xe2, 0xee, 0xae, 0xc3, 0x22, 0xab, 0x14, 0x61, 0xa7, 0x37, 0x5f, 0x95, 0xe1, 0xbc, 0xb8, 0x01, + 0x40, 0x8e, 0x26, 0xac, 0xcd, 0x6d, 0x5d, 0x9b, 0x1d, 0x2f, 0x6e, 0x7f, 0xd8, 0xee, 0x90, 0xa3, + 0x33, 0xdf, 0x15, 0x83, 0x72, 0xe5, 0x04, 0xaa, 0x4f, 0xd4, 0x22, 0x86, 0xe1, 0x36, 0x5d, 0x50, + 0x2d, 0xba, 0x03, 0xf9, 0x03, 0xf3, 0x84, 0x18, 0xda, 0x43, 0xd6, 0x00, 0x97, 0xd2, 0x4c, 0xf3, + 0xa7, 0x94, 0x94, 0xc9, 0x46, 0x59, 0xcd, 0x31, 0xee, 0x00, 0xf8, 0x02, 0x85, 0xad, 0xf2, 0xd7, + 0x24, 0x2c, 0xef, 0x12, 0x77, 0x40, 0x62, 0x91, 0xd9, 0x85, 0x82, 0x45, 0x0e, 0x5e, 0xe0, 0x18, + 0xe4, 0x29, 0x7b, 0x74, 0x08, 0x14, 0x28, 0xba, 0xe6, 0xe0, 0x30, 0x26, 0x2f, 0x31, 0xa7, 0xbc, + 0x02, 0xe3, 0x8f, 0x04, 0xc6, 0x02, 0x90, 0x7e, 0x19, 0x97, 0xc1, 0x0d, 0x28, 0xd0, 0xc3, 0xa1, + 0x91, 0xa3, 0xb1, 0x1e, 0xdd, 0x07, 0xe1, 0xb9, 0xc9, 0x53, 0x94, 0xc4, 0x31, 0xf8, 0x03, 0xb8, + 0xc2, 0x5c, 0x79, 0x96, 0xa3, 0x33, 0x0a, 0x3d, 0x39, 0xf0, 0xa5, 0xa3, 0xc9, 0x42, 0xff, 0x73, + 0x28, 0x05, 0x7e, 0x3b, 0x87, 0x39, 0x1b, 0x63, 0x5e, 0x61, 0x54, 0x53, 0xdc, 0x95, 0x5f, 0x25, + 0xa1, 0x78, 0x5b, 0xf7, 0x0e, 0x63, 0x71, 0xbd, 0x09, 0xcb, 0x53, 0xca, 0x04, 0x85, 0x84, 0x5f, + 0xb8, 0x71, 0x15, 0xf0, 0x2d, 0x40, 0xd3, 0x9b, 0x07, 0xb5, 0x84, 0x11, 0x17, 0x27, 0xb7, 0x7c, + 0xe9, 0x11, 0x79, 0x1b, 0x8a, 0x43, 0x9a, 0xc4, 0x67, 0x15, 0x32, 0x1e, 0x92, 0x42, 0x80, 0x0b, + 0x95, 0x7d, 0x79, 0x31, 0xf9, 0x4b, 0x02, 0x70, 0x93, 0x4f, 0xcb, 0xb1, 0xb8, 0xfc, 0x40, 0xed, + 0x96, 0x02, 0x85, 0x70, 0x54, 0x7f, 0xde, 0xea, 0x95, 0x0f, 0x05, 0xb0, 0x80, 0xbd, 0xe4, 0xa8, + 0xef, 0xa4, 0x32, 0x49, 0x94, 0xaa, 0xfc, 0x5e, 0x80, 0x95, 0xd0, 0xa9, 0x0d, 0xd3, 0xf2, 0x89, + 0xcb, 0xdd, 0xba, 0x01, 0x28, 0xb2, 0xb7, 0xef, 0x58, 0xcc, 0x33, 0x42, 0xcc, 0x33, 0xc5, 0x10, + 0x5b, 0x73, 0x2c, 0xea, 0x9f, 0xcf, 0xa6, 0xfd, 0x13, 0x94, 0xa9, 0x9f, 0x4c, 0xa9, 0xe4, 0x8c, + 0xfc, 0x8d, 0xf8, 0x93, 0xc7, 0x06, 0x9d, 0x41, 0xce, 0xcc, 0x6b, 0xbb, 0x8e, 0xef, 0x9c, 0xe7, + 0xae, 0xca, 0x1f, 0x33, 0x50, 0x14, 0x07, 0x03, 0x97, 0x0c, 0x74, 0xdf, 0x09, 0x54, 0xbc, 0x06, + 0x30, 0x70, 0x9d, 0xa0, 0x0b, 0x8c, 0x9f, 0xaf, 0x2c, 0x83, 0xd6, 0x1c, 0xcb, 0xc3, 0x9f, 0x41, + 0x5e, 0xe7, 0x4c, 0xa6, 0x13, 0x4d, 0x47, 0x3f, 0x9d, 0xed, 0xe9, 0xc9, 0x2d, 0xa2, 0x65, 0x2c, + 0x88, 0x71, 0x79, 0xf8, 0xc7, 0xbc, 0x45, 0x21, 0x86, 0x16, 0x53, 0x25, 0x15, 0xa9, 0x82, 0x38, + 0x76, 0x3b, 0xd2, 0x68, 0x9b, 0x47, 0x2c, 0xcd, 0x22, 0xf6, 0xce, 0x33, 0x6b, 0x32, 0x1d, 0xbf, + 0xf2, 0x2f, 0x12, 0x90, 0x8b, 0xa9, 0x47, 0x05, 0x1f, 0x8c, 0xed, 0x3e, 0x0b, 0xd2, 0x3c, 0x82, + 0x1b, 0x63, 0xbb, 0x1f, 0x0a, 0xa6, 0x02, 0xf0, 0x1a, 0x64, 0xa2, 0x9e, 0x26, 0x11, 0x3b, 0x95, + 0x11, 0x14, 0xbf, 0x09, 0xc5, 0x03, 0x96, 0x2b, 0x51, 0x66, 0xd0, 0xc3, 0x50, 0x50, 0xf3, 0x01, + 0x94, 0x67, 0xc4, 0x15, 0xf6, 0x1a, 0xc5, 0xd0, 0x69, 0xd6, 0x47, 0x2d, 0xf6, 0x03, 0xc4, 0x6d, + 0xc8, 0xea, 0xee, 0x60, 0x3c, 0x24, 0xb6, 0xef, 0x95, 0x16, 0x59, 0x44, 0xe6, 0xc9, 0xfd, 0x33, + 0x66, 0x9e, 0xc3, 0xff, 0x4a, 0x42, 0x8a, 0x5a, 0x81, 0x11, 0xe4, 0x45, 0xf9, 0x63, 0x4d, 0x56, + 0xba, 0x9a, 0xdc, 0x6b, 0xb5, 0xd0, 0x02, 0x5e, 0x82, 0xa4, 0xb8, 0xb7, 0x8d, 0x04, 0x9c, 0x87, + 0x4c, 0x55, 0x51, 0x5a, 0x9a, 0x28, 0xd7, 0x51, 0x02, 0xe7, 0x60, 0x89, 0xad, 0x14, 0x15, 0x25, + 0x71, 0x11, 0xa0, 0xa6, 0xc8, 0x35, 0xb1, 0xab, 0x89, 0xdb, 0xdb, 0x28, 0x85, 0xb3, 0x90, 0xae, + 0x29, 0x3d, 0xb9, 0x8b, 0xd2, 0x94, 0x7d, 0x57, 0xbc, 0x8f, 0x96, 0xd8, 0x8f, 0xa6, 0x8c, 0x32, + 0x18, 0x60, 0xb1, 0xd3, 0xad, 0xd7, 0xa5, 0x3d, 0x94, 0xa5, 0xc0, 0x4e, 0x6f, 0x17, 0x01, 0x15, + 0xd7, 0xe9, 0xed, 0x6a, 0x4d, 0xb9, 0x8b, 0x72, 0x74, 0xa7, 0x3d, 0x51, 0x6d, 0x8a, 0x72, 0x4d, + 0x42, 0x79, 0x8a, 0xba, 0xaf, 0xa8, 0x4c, 0x72, 0x21, 0xd8, 0xa9, 0x27, 0x77, 0x35, 0x55, 0xb9, + 0xd7, 0x41, 0x45, 0xc6, 0x77, 0x57, 0xad, 0x37, 0x1b, 0x0d, 0xb4, 0x8c, 0x31, 0x14, 0x1b, 0x4d, + 0x59, 0x6c, 0x69, 0x11, 0x37, 0xa2, 0x06, 0x05, 0x30, 0xbe, 0xe7, 0x25, 0x5c, 0x80, 0xac, 0xa8, + 0xaa, 0xe2, 0xc7, 0x4c, 0x22, 0xa6, 0x9b, 0xed, 0x74, 0x14, 0x99, 0xad, 0x2e, 0x53, 0x24, 0x5d, + 0x55, 0xd9, 0x72, 0x85, 0x6e, 0xd7, 0xe9, 0xaa, 0x4d, 0x79, 0x9b, 0xad, 0x5f, 0x61, 0x56, 0x37, + 0xbb, 0xcc, 0x05, 0xaf, 0x52, 0x43, 0xe8, 0x42, 0x51, 0xd1, 0x15, 0x9c, 0x81, 0x54, 0x4d, 0x51, + 0x55, 0x54, 0xc2, 0x25, 0x58, 0x69, 0x4b, 0x6a, 0x4d, 0x92, 0xbb, 0xcd, 0x96, 0xa4, 0xd5, 0x9b, + 0x9d, 0x9a, 0xd6, 0xdc, 0x6d, 0xb7, 0xd0, 0x6b, 0x53, 0x98, 0x9a, 0x22, 0x77, 0x03, 0x4c, 0x19, + 0x5f, 0x86, 0x65, 0xa6, 0x83, 0x52, 0xdd, 0x91, 0x6a, 0x81, 0x13, 0x5f, 0xc7, 0x2b, 0x80, 0x02, + 0x55, 0x62, 0xd0, 0xff, 0xa3, 0x1a, 0xec, 0x89, 0xaa, 0xd6, 0x56, 0xda, 0xe8, 0xff, 0x03, 0xf5, + 0xa8, 0x59, 0x6c, 0xbd, 0x8a, 0x97, 0x21, 0xd7, 0xe9, 0x6a, 0xbb, 0xe2, 0x1d, 0xa9, 0xd5, 0x94, + 0x25, 0x74, 0x95, 0x9a, 0xd3, 0xe9, 0x6a, 0xd2, 0xfd, 0xae, 0x24, 0x77, 0xd1, 0x1a, 0xb5, 0xb5, + 0xd3, 0xd5, 0x7a, 0x72, 0x53, 0x91, 0xd1, 0xb5, 0xca, 0x2d, 0x48, 0xd1, 0x23, 0x41, 0x75, 0x17, + 0x7b, 0x5d, 0x05, 0x2d, 0xb0, 0xd0, 0xd4, 0xc4, 0x96, 0xa8, 0x22, 0x81, 0xca, 0x96, 0x15, 0x59, + 0xe3, 0xeb, 0x44, 0xe5, 0x4f, 0x8b, 0xf0, 0x7a, 0xd3, 0xf6, 0x89, 0x6b, 0x11, 0xfd, 0x21, 0x31, + 0x82, 0x69, 0x3d, 0x76, 0x89, 0x7c, 0x3c, 0xd5, 0x4e, 0x7f, 0x38, 0x3b, 0x1f, 0x9f, 0x22, 0x26, + 0xb8, 0x64, 0xa6, 0x7a, 0xec, 0xd8, 0x13, 0x48, 0xe2, 0xbc, 0x27, 0x90, 0xc9, 0xf7, 0xc4, 0xe4, + 0xf9, 0xef, 0x89, 0x17, 0x3a, 0xc1, 0xa7, 0xe7, 0x6f, 0x11, 0xfe, 0xd7, 0xdf, 0x69, 0xca, 0x5f, + 0x25, 0x20, 0xcd, 0xa2, 0x83, 0x3f, 0x82, 0x94, 0x41, 0xbc, 0xfe, 0x73, 0xb5, 0x0b, 0x8c, 0xf3, + 0x59, 0xba, 0x85, 0x1a, 0xa4, 0x46, 0x8e, 0x17, 0x84, 0xf3, 0xa9, 0xaf, 0x71, 0x6d, 0xc7, 0xf3, + 0xdb, 0xc1, 0x17, 0x02, 0x9a, 0x41, 0xe1, 0x3e, 0x94, 0x19, 0xd7, 0x21, 0x13, 0x35, 0xfd, 0xa9, + 0x39, 0x9b, 0xfe, 0x88, 0xf3, 0xec, 0x65, 0x30, 0xfd, 0x22, 0x2f, 0x83, 0x95, 0x3f, 0x0b, 0x50, + 0x6c, 0xbb, 0xce, 0xe7, 0xa4, 0xef, 0x77, 0x48, 0x30, 0x5a, 0x7f, 0x04, 0x69, 0x9a, 0x91, 0xe1, + 0x99, 0x99, 0x27, 0x25, 0x03, 0x46, 0xbc, 0x0d, 0x97, 0x06, 0xc4, 0x26, 0xae, 0xee, 0xc7, 0x9a, + 0xcf, 0x60, 0x0c, 0x2d, 0x4f, 0x07, 0x86, 0x0c, 0x37, 0x82, 0x6f, 0x30, 0x5d, 0x15, 0x45, 0x4c, + 0x61, 0x57, 0x7a, 0x1d, 0x90, 0x3d, 0x66, 0xef, 0x1b, 0x9e, 0x36, 0x22, 0xae, 0x36, 0x20, 0x76, + 0x30, 0x82, 0xaa, 0x05, 0x7b, 0x3c, 0xa4, 0x17, 0x6f, 0x9b, 0xb8, 0xdb, 0xc4, 0xae, 0x7c, 0x5b, + 0x80, 0xfc, 0x3d, 0xd3, 0x36, 0x9c, 0x63, 0x7e, 0xf2, 0xd7, 0xd8, 0xd3, 0xb1, 0x6f, 0xb2, 0x2b, + 0xfe, 0x94, 0xbf, 0x0d, 0xc4, 0x41, 0xb8, 0x03, 0xd9, 0x63, 0xc6, 0xd1, 0x88, 0x94, 0xdb, 0x9c, + 0x6d, 0x6a, 0x5c, 0x38, 0x5f, 0x34, 0xa2, 0x9b, 0x2b, 0x92, 0x53, 0xfe, 0x83, 0xc0, 0xef, 0xac, + 0x0e, 0x14, 0xc2, 0x8e, 0x82, 0x34, 0x9e, 0xf7, 0xfe, 0x56, 0x27, 0x65, 0xe0, 0xbb, 0x00, 0x7c, + 0x2b, 0x2a, 0x31, 0xc1, 0x24, 0xbe, 0x3b, 0x9f, 0xce, 0x54, 0x6a, 0x4c, 0xc8, 0x07, 0xa9, 0x47, + 0x5f, 0x5e, 0x15, 0xca, 0x5f, 0x2e, 0x41, 0xba, 0xe1, 0xea, 0x43, 0x82, 0xef, 0x40, 0x6a, 0xe8, + 0x18, 0x84, 0xab, 0xfb, 0xac, 0xc2, 0x19, 0xef, 0xc6, 0xae, 0x63, 0x44, 0xe5, 0x85, 0x0a, 0xc1, + 0x77, 0x61, 0x71, 0xdf, 0x19, 0xdb, 0x86, 0x37, 0xa3, 0x6b, 0x7c, 0xba, 0xb8, 0x2a, 0x63, 0x0d, + 0x8b, 0x5d, 0x20, 0x08, 0x7f, 0x02, 0x59, 0x72, 0xd2, 0xb7, 0xc6, 0x34, 0xe9, 0xd8, 0x31, 0x2c, + 0x6e, 0xbd, 0x37, 0x97, 0x54, 0x29, 0xe4, 0x8e, 0x9e, 0x3b, 0x42, 0x40, 0xf9, 0x3b, 0x01, 0xd2, + 0x6c, 0x53, 0xba, 0x0b, 0xdb, 0x8f, 0x16, 0x4c, 0xee, 0x8a, 0xf7, 0xe6, 0xd7, 0x3d, 0x56, 0x6e, + 0xcf, 0xc4, 0xd1, 0x8b, 0xc1, 0xb4, 0x7d, 0xcd, 0x39, 0x38, 0xf0, 0x48, 0xd0, 0x89, 0x85, 0x5f, + 0x71, 0xb2, 0xa6, 0xed, 0x2b, 0x0c, 0x8c, 0xaf, 0x41, 0x9e, 0x9e, 0x0a, 0x23, 0x24, 0xa3, 0x96, + 0xe6, 0xd5, 0x1c, 0x83, 0x71, 0x92, 0x1d, 0xc8, 0x05, 0x48, 0xf6, 0xed, 0x93, 0x57, 0x92, 0x39, + 0xbe, 0x0c, 0x42, 0xc0, 0x4d, 0x75, 0x2a, 0xff, 0x56, 0x80, 0xc5, 0xc0, 0xdd, 0x58, 0x86, 0xb4, + 0xe7, 0xeb, 0xae, 0xcf, 0x0b, 0xe9, 0xd6, 0xfc, 0x66, 0x47, 0x05, 0x86, 0x8a, 0xc1, 0x75, 0x48, + 0x12, 0xdb, 0xe0, 0x09, 0xf0, 0x1c, 0xd2, 0x54, 0xca, 0x5e, 0xb9, 0x0e, 0x29, 0x9a, 0x5d, 0xb4, + 0x89, 0x53, 0x45, 0x79, 0x5b, 0x42, 0x0b, 0xb4, 0x43, 0x60, 0xfd, 0x96, 0x40, 0x3b, 0x84, 0x6d, + 0x55, 0xe9, 0xb5, 0x3b, 0x28, 0x51, 0xf9, 0x02, 0xb2, 0x91, 0xef, 0xf1, 0x15, 0xb8, 0xdc, 0x93, + 0xab, 0x4a, 0x4f, 0xae, 0x4b, 0x75, 0xad, 0xad, 0x4a, 0x35, 0xa9, 0xde, 0x94, 0xb7, 0xd1, 0xc2, + 0x24, 0xa2, 0xa1, 0xb4, 0x5a, 0xca, 0x3d, 0x8a, 0x10, 0x68, 0x7f, 0xa3, 0x34, 0x1a, 0x1d, 0xa9, + 0x1b, 0x23, 0x4f, 0xc4, 0xa0, 0x67, 0xb4, 0x49, 0xda, 0xd8, 0xd4, 0x7a, 0xaa, 0x2a, 0x05, 0x8d, + 0x1f, 0x4a, 0x55, 0x3e, 0x85, 0x6c, 0x94, 0x5d, 0xb4, 0xc7, 0x93, 0x15, 0x4d, 0xba, 0x5f, 0x6b, + 0xf5, 0x3a, 0xb4, 0xb5, 0x61, 0x9b, 0xb2, 0x65, 0x5d, 0xd2, 0xe2, 0x7c, 0x02, 0xbe, 0x04, 0x85, + 0x10, 0xc1, 0xec, 0x40, 0x09, 0xca, 0x1d, 0x82, 0xba, 0x4d, 0xa9, 0x83, 0x92, 0xe5, 0xbf, 0x25, + 0x20, 0x13, 0xd6, 0x1d, 0x2c, 0xc5, 0x86, 0x82, 0xdc, 0xd6, 0xdb, 0xcf, 0xea, 0xd5, 0xe9, 0x91, + 0xe0, 0x62, 0x6e, 0xa2, 0x2a, 0xa4, 0x0f, 0x68, 0xbc, 0xf8, 0xbc, 0x7b, 0x6b, 0x9e, 0x18, 0xab, + 0x01, 0x2b, 0x5e, 0x87, 0x89, 0x21, 0x83, 0x35, 0x21, 0xe9, 0x70, 0x34, 0x9b, 0x18, 0x3f, 0xca, + 0x90, 0xd1, 0xdd, 0x81, 0xd7, 0x34, 0x4e, 0xbc, 0xd2, 0x12, 0xab, 0xea, 0xd1, 0x9a, 0x4a, 0x09, + 0xde, 0x9a, 0xb9, 0x94, 0x4c, 0xec, 0x12, 0x9f, 0xc0, 0xec, 0xa4, 0x32, 0x09, 0x94, 0xe4, 0x73, + 0xc6, 0xef, 0x04, 0x80, 0xb3, 0xea, 0x48, 0x7b, 0x4c, 0x55, 0xb9, 0xa7, 0xc9, 0xbd, 0xdd, 0xaa, + 0xa4, 0xf2, 0x3c, 0x13, 0xe5, 0x3b, 0x41, 0xf7, 0x59, 0x97, 0xe4, 0x8e, 0xa4, 0xb1, 0x35, 0x0b, + 0x12, 0xef, 0x9d, 0x03, 0x48, 0x92, 0xb6, 0xb6, 0xb5, 0xde, 0x2e, 0xeb, 0xb0, 0xbb, 0xc1, 0xc8, + 0xc1, 0xfa, 0xea, 0x60, 0xe4, 0x68, 0x89, 0xdb, 0x68, 0x91, 0x8a, 0x6b, 0x49, 0x62, 0x1d, 0x2d, + 0xd1, 0xfc, 0x69, 0x34, 0xd5, 0x4e, 0x57, 0xdb, 0x13, 0x5b, 0x3d, 0x09, 0x65, 0xa8, 0xfc, 0x96, + 0x18, 0xad, 0xb3, 0x54, 0x9a, 0xdc, 0xbd, 0xcd, 0x97, 0x70, 0xf3, 0x67, 0x50, 0x9c, 0xfc, 0x84, + 0x42, 0x13, 0xbf, 0xdd, 0xab, 0xb6, 0x9a, 0x35, 0xb4, 0x80, 0x5f, 0x83, 0x57, 0x82, 0xdf, 0x74, + 0x10, 0x60, 0xb3, 0x12, 0x47, 0x09, 0xd5, 0x77, 0x1e, 0x7d, 0xbb, 0xba, 0xf0, 0xe8, 0xf1, 0xaa, + 0xf0, 0xf5, 0xe3, 0x55, 0xe1, 0x9b, 0xc7, 0xab, 0xc2, 0x3f, 0x1e, 0xaf, 0x0a, 0xbf, 0x7c, 0xb2, + 0xba, 0xf0, 0xf5, 0x93, 0xd5, 0x85, 0x6f, 0x9e, 0xac, 0x2e, 0x7c, 0x92, 0x8b, 0xfd, 0x67, 0xc3, + 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x21, 0x86, 0xfa, 0xc9, 0x21, 0x00, 0x00, } diff --git a/pkg/sql/execinfrapb/processors_sql.proto b/pkg/sql/execinfrapb/processors_sql.proto index 4cce0af21f57..bd774b7696b8 100644 --- a/pkg/sql/execinfrapb/processors_sql.proto +++ b/pkg/sql/execinfrapb/processors_sql.proto @@ -611,6 +611,7 @@ message AggregatorSpec { STDDEV_POP = 30; ST_MAKELINE = 31; ST_EXTENT = 32; + ST_UNION = 33; } enum Type { diff --git a/pkg/sql/logictest/testdata/logic_test/drop_table b/pkg/sql/logictest/testdata/logic_test/drop_table index 4e4a6aeb2686..4ea6d5d32859 100644 --- a/pkg/sql/logictest/testdata/logic_test/drop_table +++ b/pkg/sql/logictest/testdata/logic_test/drop_table @@ -56,3 +56,22 @@ CREATE TABLE a (id INT PRIMARY KEY) query I SELECT * FROM a ---- + +user testuser + +statement ok +SET experimental_enable_user_defined_schemas = true + +statement ok +CREATE SCHEMA s + +user root + +statement ok +CREATE TABLE s.t() + +user testuser + +# Being the owner of schema s should allow testuser to drop table s.t. +statement ok +DROP TABLE s.t diff --git a/pkg/sql/logictest/testdata/logic_test/geospatial b/pkg/sql/logictest/testdata/logic_test/geospatial index 09402283e4d7..0011822700c3 100644 --- a/pkg/sql/logictest/testdata/logic_test/geospatial +++ b/pkg/sql/logictest/testdata/logic_test/geospatial @@ -811,26 +811,33 @@ FROM parse_test ORDER BY id ASC 0101000000000000000000F87F000000000000F87F 0101000020E6100000000000000000F87F000000000000F87F 0101000020E6100000000000000000F87F000000000000F87F 0020000001000010E67FF80000000000007FF8000000000000 NULL NULL NULL NULL -subtest ST_PointFromGeoHash query T -SELECT ST_AsText(ST_PointFromGeoHash('s000000000000000')) ----- -POINT (0 0) - -query T -SELECT ST_AsText(ST_PointFromGeoHash('kkqnpkue9ktbpe5')) ----- -POINT (20.012345 -20.012345) - -query T -SELECT ST_AsText(ST_PointFromGeoHash('w000000000000000',16)) +SELECT + ST_AsText(g) +FROM ( VALUES + (ST_PointFromGeoHash('s000000000000000')), + (ST_PointFromGeoHash('kkqnpkue9ktbpe5')), + (ST_PointFromGeoHash('w000000000000000')), + (ST_PointFromGeoHash('w000000000000000',5)), + (ST_GeomFromGeoHash('s000000000000000')), + (ST_GeomFromGeoHash('kkqnpkue9ktbpe5')), + (ST_GeomFromGeoHash('w000000000000000')), + (ST_GeomFromGeoHash('w000000000000000',5)) +) tbl(g) ---- -POINT (90 0) +POINT (0.000000000163709 0.000000000081855) +POINT (20.01234499963175 -20.01234499963175) +POINT (90.000000000163709 0.000000000081855) +POINT (90.02197265625 0.02197265625) +POLYGON ((0 0, 0 0.000000000163709, 0.000000000327418 0.000000000163709, 0.000000000327418 0, 0 0)) +POLYGON ((20.012344998976914 -20.012345000286587, 20.012344998976914 -20.012344998976914, 20.012345000286587 -20.012344998976914, 20.012345000286587 -20.012345000286587, 20.012344998976914 -20.012345000286587)) +POLYGON ((90 0, 90 0.000000000163709, 90.000000000327418 0.000000000163709, 90.000000000327418 0, 90 0)) +POLYGON ((90 0, 90 0.0439453125, 90.0439453125 0.0439453125, 90.0439453125 0, 90 0)) statement error pq: st_pointfromgeohash\(\): geohash decode '----': invalid character at index 0 SELECT ST_AsText(ST_PointFromGeoHash('----')) -statement error pq: st_pointfromgeohash\(\): Length of geohash must be greater than 0 +statement error pq: st_pointfromgeohash\(\): length of GeoHash must be greater than 0 SELECT ST_AsText(ST_PointFromGeoHash('')) query TTTTTTTT @@ -965,160 +972,6 @@ Square overlapping left and right square 1.1 1.1 0 0 4.2 4.2 # Topology operators. -query TTT -SELECT - a.dsc, - b.dsc, - ST_AsEWKT(ST_Union(a.geom, b.geom)) -FROM geom_operators_test a -JOIN geom_operators_test b ON (1=1) -ORDER BY a.dsc, b.dsc ----- -Empty GeometryCollection Empty GeometryCollection GEOMETRYCOLLECTION EMPTY -Empty GeometryCollection Empty LineString LINESTRING EMPTY -Empty GeometryCollection Empty Point POINT EMPTY -Empty GeometryCollection Faraway point POINT (5 5) -Empty GeometryCollection Line going through left and right square LINESTRING (-0.5 0.5, 0.5 0.5) -Empty GeometryCollection NULL NULL -Empty GeometryCollection Nested Geometry Collection GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) -Empty GeometryCollection Point middle of Left Square POINT (-0.5 0.5) -Empty GeometryCollection Point middle of Right Square POINT (0.5 0.5) -Empty GeometryCollection Square (left) POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) -Empty GeometryCollection Square (right) POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) -Empty GeometryCollection Square overlapping left and right square POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) -Empty LineString Empty GeometryCollection GEOMETRYCOLLECTION EMPTY -Empty LineString Empty LineString LINESTRING EMPTY -Empty LineString Empty Point POINT EMPTY -Empty LineString Faraway point POINT (5 5) -Empty LineString Line going through left and right square LINESTRING (-0.5 0.5, 0.5 0.5) -Empty LineString NULL NULL -Empty LineString Nested Geometry Collection GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) -Empty LineString Point middle of Left Square POINT (-0.5 0.5) -Empty LineString Point middle of Right Square POINT (0.5 0.5) -Empty LineString Square (left) POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) -Empty LineString Square (right) POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) -Empty LineString Square overlapping left and right square POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) -Empty Point Empty GeometryCollection GEOMETRYCOLLECTION EMPTY -Empty Point Empty LineString LINESTRING EMPTY -Empty Point Empty Point POINT EMPTY -Empty Point Faraway point POINT (5 5) -Empty Point Line going through left and right square LINESTRING (-0.5 0.5, 0.5 0.5) -Empty Point NULL NULL -Empty Point Nested Geometry Collection GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) -Empty Point Point middle of Left Square POINT (-0.5 0.5) -Empty Point Point middle of Right Square POINT (0.5 0.5) -Empty Point Square (left) POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) -Empty Point Square (right) POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) -Empty Point Square overlapping left and right square POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) -Faraway point Empty GeometryCollection POINT (5 5) -Faraway point Empty LineString POINT (5 5) -Faraway point Empty Point POINT (5 5) -Faraway point Faraway point POINT (5 5) -Faraway point Line going through left and right square GEOMETRYCOLLECTION (POINT (5 5), LINESTRING (-0.5 0.5, 0.5 0.5)) -Faraway point NULL NULL -Faraway point Nested Geometry Collection GEOMETRYCOLLECTION (POINT (5 5), GEOMETRYCOLLECTION (POINT (0 0))) -Faraway point Point middle of Left Square MULTIPOINT (5 5, -0.5 0.5) -Faraway point Point middle of Right Square MULTIPOINT (5 5, 0.5 0.5) -Faraway point Square (left) GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0))) -Faraway point Square (right) GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))) -Faraway point Square overlapping left and right square GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0))) -Line going through left and right square Empty GeometryCollection LINESTRING (-0.5 0.5, 0.5 0.5) -Line going through left and right square Empty LineString LINESTRING (-0.5 0.5, 0.5 0.5) -Line going through left and right square Empty Point LINESTRING (-0.5 0.5, 0.5 0.5) -Line going through left and right square Faraway point GEOMETRYCOLLECTION (LINESTRING (-0.5 0.5, 0.5 0.5), POINT (5 5)) -Line going through left and right square Line going through left and right square LINESTRING (-0.5 0.5, 0.5 0.5) -Line going through left and right square NULL NULL -Line going through left and right square Nested Geometry Collection GEOMETRYCOLLECTION (LINESTRING (-0.5 0.5, 0.5 0.5), GEOMETRYCOLLECTION (POINT (0 0))) -Line going through left and right square Point middle of Left Square LINESTRING (-0.5 0.5, 0.5 0.5) -Line going through left and right square Point middle of Right Square LINESTRING (-0.5 0.5, 0.5 0.5) -Line going through left and right square Square (left) GEOMETRYCOLLECTION (LINESTRING (0 0.5, 0.5 0.5), POLYGON ((0 0.5, 0 0, -1 0, -1 1, 0 1, 0 0.5))) -Line going through left and right square Square (right) GEOMETRYCOLLECTION (LINESTRING (-0.5 0.5, 0 0.5), POLYGON ((0 0.5, 0 1, 1 1, 1 0, 0 0, 0 0.5))) -Line going through left and right square Square overlapping left and right square GEOMETRYCOLLECTION (LINESTRING (-0.5 0.5, -0.1 0.5), POLYGON ((-0.1 0.5, -0.1 1, 1 1, 1 0, -0.1 0, -0.1 0.5))) -NULL Empty GeometryCollection NULL -NULL Empty LineString NULL -NULL Empty Point NULL -NULL Faraway point NULL -NULL Line going through left and right square NULL -NULL NULL NULL -NULL Nested Geometry Collection NULL -NULL Point middle of Left Square NULL -NULL Point middle of Right Square NULL -NULL Square (left) NULL -NULL Square (right) NULL -NULL Square overlapping left and right square NULL -Nested Geometry Collection Empty GeometryCollection GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) -Nested Geometry Collection Empty LineString GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) -Nested Geometry Collection Empty Point GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) -Nested Geometry Collection Faraway point GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0)), POINT (5 5)) -Nested Geometry Collection Line going through left and right square GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0)), LINESTRING (-0.5 0.5, 0.5 0.5)) -Nested Geometry Collection NULL NULL -Nested Geometry Collection Nested Geometry Collection POINT (0 0) -Nested Geometry Collection Point middle of Left Square GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0)), POINT (-0.5 0.5)) -Nested Geometry Collection Point middle of Right Square GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0)), POINT (0.5 0.5)) -Nested Geometry Collection Square (left) POLYGON ((-1 0, -1 1, 0 1, 0 0, -1 0)) -Nested Geometry Collection Square (right) POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) -Nested Geometry Collection Square overlapping left and right square POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) -Point middle of Left Square Empty GeometryCollection POINT (-0.5 0.5) -Point middle of Left Square Empty LineString POINT (-0.5 0.5) -Point middle of Left Square Empty Point POINT (-0.5 0.5) -Point middle of Left Square Faraway point MULTIPOINT (-0.5 0.5, 5 5) -Point middle of Left Square Line going through left and right square LINESTRING (-0.5 0.5, 0.5 0.5) -Point middle of Left Square NULL NULL -Point middle of Left Square Nested Geometry Collection GEOMETRYCOLLECTION (POINT (-0.5 0.5), GEOMETRYCOLLECTION (POINT (0 0))) -Point middle of Left Square Point middle of Left Square POINT (-0.5 0.5) -Point middle of Left Square Point middle of Right Square MULTIPOINT (-0.5 0.5, 0.5 0.5) -Point middle of Left Square Square (left) POLYGON ((-1 0, -1 1, 0 1, 0 0, -1 0)) -Point middle of Left Square Square (right) GEOMETRYCOLLECTION (POINT (-0.5 0.5), POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))) -Point middle of Left Square Square overlapping left and right square GEOMETRYCOLLECTION (POINT (-0.5 0.5), POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0))) -Point middle of Right Square Empty GeometryCollection POINT (0.5 0.5) -Point middle of Right Square Empty LineString POINT (0.5 0.5) -Point middle of Right Square Empty Point POINT (0.5 0.5) -Point middle of Right Square Faraway point MULTIPOINT (0.5 0.5, 5 5) -Point middle of Right Square Line going through left and right square LINESTRING (-0.5 0.5, 0.5 0.5) -Point middle of Right Square NULL NULL -Point middle of Right Square Nested Geometry Collection GEOMETRYCOLLECTION (POINT (0.5 0.5), GEOMETRYCOLLECTION (POINT (0 0))) -Point middle of Right Square Point middle of Left Square MULTIPOINT (0.5 0.5, -0.5 0.5) -Point middle of Right Square Point middle of Right Square POINT (0.5 0.5) -Point middle of Right Square Square (left) GEOMETRYCOLLECTION (POINT (0.5 0.5), POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0))) -Point middle of Right Square Square (right) POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) -Point middle of Right Square Square overlapping left and right square POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) -Square (left) Empty GeometryCollection POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) -Square (left) Empty LineString POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) -Square (left) Empty Point POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) -Square (left) Faraway point GEOMETRYCOLLECTION (POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)), POINT (5 5)) -Square (left) Line going through left and right square GEOMETRYCOLLECTION (LINESTRING (0 0.5, 0.5 0.5), POLYGON ((0 0.5, 0 0, -1 0, -1 1, 0 1, 0 0.5))) -Square (left) NULL NULL -Square (left) Nested Geometry Collection POLYGON ((-1 0, -1 1, 0 1, 0 0, -1 0)) -Square (left) Point middle of Left Square POLYGON ((-1 0, -1 1, 0 1, 0 0, -1 0)) -Square (left) Point middle of Right Square GEOMETRYCOLLECTION (POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)), POINT (0.5 0.5)) -Square (left) Square (left) POLYGON ((0 0, -1 0, -1 1, 0 1, 0 0)) -Square (left) Square (right) POLYGON ((0 0, -1 0, -1 1, 0 1, 1 1, 1 0, 0 0)) -Square (left) Square overlapping left and right square POLYGON ((-0.1 0, -1 0, -1 1, -0.1 1, 0 1, 1 1, 1 0, 0 0, -0.1 0)) -Square (right) Empty GeometryCollection POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) -Square (right) Empty LineString POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) -Square (right) Empty Point POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) -Square (right) Faraway point GEOMETRYCOLLECTION (POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)), POINT (5 5)) -Square (right) Line going through left and right square GEOMETRYCOLLECTION (LINESTRING (-0.5 0.5, 0 0.5), POLYGON ((0 0.5, 0 1, 1 1, 1 0, 0 0, 0 0.5))) -Square (right) NULL NULL -Square (right) Nested Geometry Collection POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) -Square (right) Point middle of Left Square GEOMETRYCOLLECTION (POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)), POINT (-0.5 0.5)) -Square (right) Point middle of Right Square POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) -Square (right) Square (left) POLYGON ((0 1, 1 1, 1 0, 0 0, -1 0, -1 1, 0 1)) -Square (right) Square (right) POLYGON ((1 0, 0 0, 0 1, 1 1, 1 0)) -Square (right) Square overlapping left and right square POLYGON ((1 0, 0 0, -0.1 0, -0.1 1, 0 1, 1 1, 1 0)) -Square overlapping left and right square Empty GeometryCollection POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) -Square overlapping left and right square Empty LineString POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) -Square overlapping left and right square Empty Point POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) -Square overlapping left and right square Faraway point GEOMETRYCOLLECTION (POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)), POINT (5 5)) -Square overlapping left and right square Line going through left and right square GEOMETRYCOLLECTION (LINESTRING (-0.5 0.5, -0.1 0.5), POLYGON ((-0.1 0.5, -0.1 1, 1 1, 1 0, -0.1 0, -0.1 0.5))) -Square overlapping left and right square NULL NULL -Square overlapping left and right square Nested Geometry Collection POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) -Square overlapping left and right square Point middle of Left Square GEOMETRYCOLLECTION (POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)), POINT (-0.5 0.5)) -Square overlapping left and right square Point middle of Right Square POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) -Square overlapping left and right square Square (left) POLYGON ((0 0, -0.1 0, -1 0, -1 1, -0.1 1, 0 1, 1 1, 1 0, 0 0)) -Square overlapping left and right square Square (right) POLYGON ((0 0, -0.1 0, -0.1 1, 0 1, 1 1, 1 0, 0 0)) -Square overlapping left and right square Square overlapping left and right square POLYGON ((1 0, -0.1 0, -0.1 1, 1 1, 1 0)) - query TTTB SELECT a.dsc, @@ -4321,6 +4174,23 @@ SELECT ST_Extent(g::geometry) FROM ( VALUES (NULL), ('POINT EMPTY') ) t(g) ---- NULL +query T +SELECT ST_AsEWKT(ST_Union(g::geometry)) FROM ( VALUES (NULL) ) tbl(g) +---- +NULL + +query T +SELECT ST_AsEWKT(ST_Union(g::geometry)) FROM ( VALUES (NULL), ('POINT(1 0)') ) tbl(g) +---- +POINT (1 0) + +statement error operation on mixed SRIDs forbidden +SELECT ST_AsEWKT(ST_Union(g::geometry)) FROM ( VALUES ('POINT(1 0)'), ('SRID=3857;POINT(1 0)') ) tbl(g) + +query T +SELECT ST_AsEWKT(ST_Union(g::geometry)) FROM ( VALUES (NULL), ('POINT(1 0)'), ('LINESTRING(0 0, 5 0)')) tbl(g) +---- +LINESTRING (0 0, 5 0) subtest set_point_test diff --git a/pkg/sql/logictest/testdata/logic_test/geospatial_bbox b/pkg/sql/logictest/testdata/logic_test/geospatial_bbox index 53b54716a0e4..356a094de17f 100644 --- a/pkg/sql/logictest/testdata/logic_test/geospatial_bbox +++ b/pkg/sql/logictest/testdata/logic_test/geospatial_bbox @@ -226,3 +226,20 @@ NULL NULL BOX(5 5,5 5) BOX(4 5,9 10) + +subtest st_box2dfromgeohash + +query T +SELECT + g +FROM ( VALUES + (ST_Box2DFromGeoHash('s000000000000000')), + (ST_Box2DFromGeoHash('kkqnpkue9ktbpe5')), + (ST_Box2DFromGeoHash('w000000000000000')), + (ST_Box2DFromGeoHash('w000000000000000',5)) +) tbl(g) +---- +BOX(0 0,0.00000000032741809263825417 0.00000000016370904631912708) +BOX(20.012344998976914 -20.012345000286587,20.012345000286587 -20.012344998976914) +BOX(90 0,90.00000000032742 0.00000000016370904631912708) +BOX(90 0,90.0439453125 0.0439453125) diff --git a/pkg/sql/opt/invertedexpr/expression.go b/pkg/sql/opt/invertedexpr/expression.go index 85f74b1abcd7..beb03fc4e89a 100644 --- a/pkg/sql/opt/invertedexpr/expression.go +++ b/pkg/sql/opt/invertedexpr/expression.go @@ -383,12 +383,12 @@ func (s *SpanExpression) ToProto() *SpanExpressionProto { } func getProtoSpans(spans []InvertedSpan) []SpanExpressionProto_Span { - out := make([]SpanExpressionProto_Span, 0, len(spans)) + out := make([]SpanExpressionProto_Span, len(spans)) for i := range spans { - out = append(out, SpanExpressionProto_Span{ + out[i] = SpanExpressionProto_Span{ Start: spans[i].Start, End: spans[i].End, - }) + } } return out } diff --git a/pkg/sql/opt/operator.go b/pkg/sql/opt/operator.go index d68f1bda401d..340455f64464 100644 --- a/pkg/sql/opt/operator.go +++ b/pkg/sql/opt/operator.go @@ -209,6 +209,7 @@ var AggregateOpReverseMap = map[Operator]string{ VarPopOp: "var_pop", StdDevPopOp: "stddev_pop", STMakeLineOp: "st_makeline", + STUnionOp: "st_union", STExtentOp: "st_extent", } @@ -305,7 +306,7 @@ func AggregateIgnoresNulls(op Operator) bool { case AnyNotNullAggOp, AvgOp, BitAndAggOp, BitOrAggOp, BoolAndOp, BoolOrOp, ConstNotNullAggOp, CorrOp, CountOp, MaxOp, MinOp, SqrDiffOp, StdDevOp, StringAggOp, SumOp, SumIntOp, VarianceOp, XorAggOp, PercentileDiscOp, - PercentileContOp, STMakeLineOp, STExtentOp, StdDevPopOp, VarPopOp: + PercentileContOp, STMakeLineOp, STExtentOp, STUnionOp, StdDevPopOp, VarPopOp: return true case ArrayAggOp, ConcatAggOp, ConstAggOp, CountRowsOp, FirstAggOp, JsonAggOp, @@ -328,7 +329,7 @@ func AggregateIsNullOnEmpty(op Operator) bool { ConstNotNullAggOp, CorrOp, FirstAggOp, JsonAggOp, JsonbAggOp, MaxOp, MinOp, SqrDiffOp, StdDevOp, STMakeLineOp, StringAggOp, SumOp, SumIntOp, VarianceOp, XorAggOp, PercentileDiscOp, PercentileContOp, - JsonObjectAggOp, JsonbObjectAggOp, StdDevPopOp, STExtentOp, VarPopOp: + JsonObjectAggOp, JsonbObjectAggOp, StdDevPopOp, STExtentOp, STUnionOp, VarPopOp: return true case CountOp, CountRowsOp: @@ -354,7 +355,7 @@ func AggregateIsNeverNullOnNonNullInput(op Operator) bool { ConstNotNullAggOp, CountOp, CountRowsOp, FirstAggOp, JsonAggOp, JsonbAggOp, MaxOp, MinOp, SqrDiffOp, STMakeLineOp, StringAggOp, SumOp, SumIntOp, XorAggOp, PercentileDiscOp, PercentileContOp, - JsonObjectAggOp, JsonbObjectAggOp, StdDevPopOp, STExtentOp, VarPopOp: + JsonObjectAggOp, JsonbObjectAggOp, StdDevPopOp, STExtentOp, STUnionOp, VarPopOp: return true case VarianceOp, StdDevOp, CorrOp: @@ -395,7 +396,7 @@ func AggregatesCanMerge(inner, outer Operator) bool { case AnyNotNullAggOp, BitAndAggOp, BitOrAggOp, BoolAndOp, BoolOrOp, ConstAggOp, ConstNotNullAggOp, FirstAggOp, - MaxOp, MinOp, STMakeLineOp, STExtentOp, SumOp, SumIntOp, XorAggOp: + MaxOp, MinOp, STMakeLineOp, STExtentOp, STUnionOp, SumOp, SumIntOp, XorAggOp: return inner == outer case CountOp, CountRowsOp: @@ -418,7 +419,7 @@ func AggregatesCanMerge(inner, outer Operator) bool { func AggregateIgnoresDuplicates(op Operator) bool { switch op { case AnyNotNullAggOp, BitAndAggOp, BitOrAggOp, BoolAndOp, BoolOrOp, - ConstAggOp, ConstNotNullAggOp, FirstAggOp, MaxOp, MinOp, STExtentOp: + ConstAggOp, ConstNotNullAggOp, FirstAggOp, MaxOp, MinOp, STExtentOp, STUnionOp: return true case ArrayAggOp, AvgOp, ConcatAggOp, CountOp, CorrOp, CountRowsOp, SumIntOp, diff --git a/pkg/sql/opt/ops/scalar.opt b/pkg/sql/opt/ops/scalar.opt index 2cb9c8562440..77727f8c6c76 100644 --- a/pkg/sql/opt/ops/scalar.opt +++ b/pkg/sql/opt/ops/scalar.opt @@ -873,6 +873,11 @@ define STExtent { Input ScalarExpr } +[Scalar, Aggregate] +define STUnion { + Input ScalarExpr +} + [Scalar, Aggregate] define XorAgg { Input ScalarExpr diff --git a/pkg/sql/opt/optbuilder/groupby.go b/pkg/sql/opt/optbuilder/groupby.go index a3d896391e9a..00caca9e2136 100644 --- a/pkg/sql/opt/optbuilder/groupby.go +++ b/pkg/sql/opt/optbuilder/groupby.go @@ -827,6 +827,8 @@ func (b *Builder) constructAggregate(name string, args []opt.ScalarExpr) opt.Sca return b.factory.ConstructSTMakeLine(args[0]) case "st_extent": return b.factory.ConstructSTExtent(args[0]) + case "st_union": + return b.factory.ConstructSTUnion(args[0]) case "xor_agg": return b.factory.ConstructXorAgg(args[0]) case "json_agg": diff --git a/pkg/sql/rowexec/inverted_expr_evaluator.go b/pkg/sql/rowexec/inverted_expr_evaluator.go index 36c899268b3e..b458cd8ec018 100644 --- a/pkg/sql/rowexec/inverted_expr_evaluator.go +++ b/pkg/sql/rowexec/inverted_expr_evaluator.go @@ -240,14 +240,14 @@ type batchedInvertedExprEvaluator struct { // Spans here are in sorted order and non-overlapping. fragmentedSpans []invertedSpanRoutingInfo - // Temporary state used for constructing fragmentedSpans. All spans here - // have the same start key. They are not sorted by end key. - pendingSpans []invertedSpanRoutingInfo + // Temporary state used during initialization. + routingSpans []invertedSpanRoutingInfo } // Helper used in building fragmentedSpans using pendingSpans. pendingSpans // contains spans with the same start key. This fragments and removes all // spans up to end key fragmentUntil (or all spans if fragmentUntil == nil). +// It then returns the remaining pendingSpans. // // Example 1: // pendingSpans contains @@ -276,15 +276,15 @@ type batchedInvertedExprEvaluator struct { // c-e-f f-i // c-e func (b *batchedInvertedExprEvaluator) fragmentPendingSpans( - fragmentUntil invertedexpr.EncInvertedVal, -) { + pendingSpans []invertedSpanRoutingInfo, fragmentUntil invertedexpr.EncInvertedVal, +) []invertedSpanRoutingInfo { // The start keys are the same, so this only sorts in increasing // order of end keys. - sort.Slice(b.pendingSpans, func(i, j int) bool { - return bytes.Compare(b.pendingSpans[i].span.End, b.pendingSpans[j].span.End) < 0 + sort.Slice(pendingSpans, func(i, j int) bool { + return bytes.Compare(pendingSpans[i].span.End, pendingSpans[j].span.End) < 0 }) - for len(b.pendingSpans) > 0 { - if fragmentUntil != nil && bytes.Compare(fragmentUntil, b.pendingSpans[0].span.Start) <= 0 { + for len(pendingSpans) > 0 { + if fragmentUntil != nil && bytes.Compare(fragmentUntil, pendingSpans[0].span.Start) <= 0 { break } // The prefix of pendingSpans that will be completely consumed when @@ -294,7 +294,7 @@ func (b *batchedInvertedExprEvaluator) fragmentPendingSpans( var end invertedexpr.EncInvertedVal // The start of the fragment after the next fragment. var nextStart invertedexpr.EncInvertedVal - if fragmentUntil != nil && bytes.Compare(fragmentUntil, b.pendingSpans[0].span.End) < 0 { + if fragmentUntil != nil && bytes.Compare(fragmentUntil, pendingSpans[0].span.End) < 0 { // Can't completely remove any spans from pendingSpans, but a prefix // of these spans will be removed removeSize = 0 @@ -303,40 +303,43 @@ func (b *batchedInvertedExprEvaluator) fragmentPendingSpans( } else { // We can remove all spans whose end key is the same as span[0]. // The end of span[0] is also the end key of this fragment. - removeSize = b.pendingLenWithSameEnd() - end = b.pendingSpans[0].span.End + removeSize = b.pendingLenWithSameEnd(pendingSpans) + end = pendingSpans[0].span.End nextStart = end } // The next span to be added to fragmentedSpans. nextSpan := invertedSpanRoutingInfo{ span: invertedSpan{ - Start: b.pendingSpans[0].span.Start, + Start: pendingSpans[0].span.Start, End: end, }, } - for i := 0; i < len(b.pendingSpans); i++ { + for i := 0; i < len(pendingSpans); i++ { if i >= removeSize { // This span is not completely removed so adjust its start. - b.pendingSpans[i].span.Start = nextStart + pendingSpans[i].span.Start = nextStart } // All spans in pendingSpans contribute to exprAndSetIndexList. nextSpan.exprAndSetIndexList = - append(nextSpan.exprAndSetIndexList, b.pendingSpans[i].exprAndSetIndexList...) + append(nextSpan.exprAndSetIndexList, pendingSpans[i].exprAndSetIndexList...) } b.fragmentedSpans = append(b.fragmentedSpans, nextSpan) - b.pendingSpans = b.pendingSpans[removeSize:] + pendingSpans = pendingSpans[removeSize:] if removeSize == 0 { // fragmentUntil was earlier than the smallest End key in the pending // spans, so cannot fragment any more. break } } + return pendingSpans } -func (b *batchedInvertedExprEvaluator) pendingLenWithSameEnd() int { +func (b *batchedInvertedExprEvaluator) pendingLenWithSameEnd( + pendingSpans []invertedSpanRoutingInfo, +) int { length := 1 - for i := 1; i < len(b.pendingSpans); i++ { - if !bytes.Equal(b.pendingSpans[0].span.End, b.pendingSpans[i].span.End) { + for i := 1; i < len(pendingSpans); i++ { + if !bytes.Equal(pendingSpans[0].span.End, pendingSpans[i].span.End) { break } length++ @@ -353,7 +356,6 @@ func (b *batchedInvertedExprEvaluator) init() []invertedSpan { b.exprEvals = b.exprEvals[:len(b.exprs)] } // Initial spans fetched from all expressions. - var routingSpans []invertedSpanRoutingInfo for i, expr := range b.exprs { if expr == nil { b.exprEvals[i] = nil @@ -363,7 +365,7 @@ func (b *batchedInvertedExprEvaluator) init() []invertedSpan { exprSpans := b.exprEvals[i].getSpansAndSetIndex() for _, spans := range exprSpans { for _, span := range spans.spans { - routingSpans = append(routingSpans, + b.routingSpans = append(b.routingSpans, invertedSpanRoutingInfo{ span: span, exprAndSetIndexList: []exprAndSetIndex{{exprIndex: i, setIndex: spans.setIndex}}, @@ -372,30 +374,35 @@ func (b *batchedInvertedExprEvaluator) init() []invertedSpan { } } } - if len(routingSpans) == 0 { + if len(b.routingSpans) == 0 { return nil } // Sort the routingSpans in increasing order of start key, and for equal // start keys in increasing order of end key. - sort.Slice(routingSpans, func(i, j int) bool { - cmp := bytes.Compare(routingSpans[i].span.Start, routingSpans[j].span.Start) + sort.Slice(b.routingSpans, func(i, j int) bool { + cmp := bytes.Compare(b.routingSpans[i].span.Start, b.routingSpans[j].span.Start) if cmp == 0 { - cmp = bytes.Compare(routingSpans[i].span.End, routingSpans[j].span.End) + cmp = bytes.Compare(b.routingSpans[i].span.End, b.routingSpans[j].span.End) } return cmp < 0 }) // The union of the spans, which is returned from this function. var coveringSpans []invertedSpan - currentCoveringSpan := routingSpans[0].span - b.pendingSpans = append(b.pendingSpans, routingSpans[0]) + currentCoveringSpan := b.routingSpans[0].span + // Create a slice of pendingSpans to be fragmented by windowing over the + // full collection of routingSpans. All spans in a given window have the + // same start key. They are not sorted by end key. + pendingSpans := b.routingSpans[:1] // This loop does both the union of the routingSpans and fragments the - // routingSpans. - for i := 1; i < len(routingSpans); i++ { - span := routingSpans[i] - if bytes.Compare(b.pendingSpans[0].span.Start, span.span.Start) < 0 { - b.fragmentPendingSpans(span.span.Start) + // routingSpans. The pendingSpans slice contains a subsequence of the + // routingSpans slice, that when passed to fragmentPendingSpans will be + // mutated by it. + for i := 1; i < len(b.routingSpans); i++ { + span := b.routingSpans[i] + if bytes.Compare(pendingSpans[0].span.Start, span.span.Start) < 0 { + pendingSpans = b.fragmentPendingSpans(pendingSpans, span.span.Start) if bytes.Compare(currentCoveringSpan.End, span.span.Start) < 0 { coveringSpans = append(coveringSpans, currentCoveringSpan) currentCoveringSpan = span.span @@ -405,10 +412,11 @@ func (b *batchedInvertedExprEvaluator) init() []invertedSpan { } else if bytes.Compare(currentCoveringSpan.End, span.span.End) < 0 { currentCoveringSpan.End = span.span.End } - // Add this span to the pending list. - b.pendingSpans = append(b.pendingSpans, span) + // Add this span to the pending list by expanding the window over + // b.routingSpans. + pendingSpans = pendingSpans[:len(pendingSpans)+1] } - b.fragmentPendingSpans(nil) + b.fragmentPendingSpans(pendingSpans, nil) coveringSpans = append(coveringSpans, currentCoveringSpan) return coveringSpans } @@ -442,5 +450,5 @@ func (b *batchedInvertedExprEvaluator) reset() { b.exprs = b.exprs[:0] b.exprEvals = b.exprEvals[:0] b.fragmentedSpans = b.fragmentedSpans[:0] - b.pendingSpans = b.pendingSpans[:0] + b.routingSpans = b.routingSpans[:0] } diff --git a/pkg/sql/rowexec/inverted_joiner.go b/pkg/sql/rowexec/inverted_joiner.go index 840dd7cd7445..9d5fd300748f 100644 --- a/pkg/sql/rowexec/inverted_joiner.go +++ b/pkg/sql/rowexec/inverted_joiner.go @@ -311,9 +311,9 @@ func (ij *invertedJoiner) generateSpan(enc []byte) (roachpb.Span, error) { return span, err } -func (ij *invertedJoiner) generateSpans(invertedSpans []invertedSpan) (roachpb.Spans, error) { - var spans []roachpb.Span - for _, span := range invertedSpans { +func (ij *invertedJoiner) generateSpans(invertedSpans []invertedSpan) ([]roachpb.Span, error) { + spans := make([]roachpb.Span, len(invertedSpans)) + for i, span := range invertedSpans { startSpan, err := ij.generateSpan(span.Start) if err != nil { return nil, err @@ -324,7 +324,7 @@ func (ij *invertedJoiner) generateSpans(invertedSpans []invertedSpan) (roachpb.S return nil, err } startSpan.EndKey = endSpan.Key - spans = append(spans, startSpan) + spans[i] = startSpan } return spans, nil } diff --git a/pkg/sql/sem/builtins/aggregate_builtins.go b/pkg/sql/sem/builtins/aggregate_builtins.go index da3b6ea204cc..5625fc780526 100644 --- a/pkg/sql/sem/builtins/aggregate_builtins.go +++ b/pkg/sql/sem/builtins/aggregate_builtins.go @@ -20,6 +20,8 @@ import ( "github.com/cockroachdb/apd/v2" "github.com/cockroachdb/cockroach/pkg/geo" + "github.com/cockroachdb/cockroach/pkg/geo/geopb" + "github.com/cockroachdb/cockroach/pkg/geo/geos" "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" @@ -398,6 +400,26 @@ var aggregates = map[string]builtinDefinition{ tree.VolatilityImmutable, ), ), + "st_union": makeBuiltin( + tree.FunctionProperties{ + Class: tree.AggregateClass, + NullableArgs: true, + AvailableOnPublicSchema: true, + }, + makeAggOverload( + []*types.T{types.Geometry}, + types.Geometry, + func( + params []*types.T, evalCtx *tree.EvalContext, arguments tree.Datums, + ) tree.AggregateFunc { + return &stUnionAgg{} + }, + infoBuilder{ + info: "Applies a spatial union to the geometries provided.", + }.String(), + tree.VolatilityImmutable, + ), + ), AnyNotNull: makePrivate(makeBuiltin(aggProps(), makeAggOverloadWithReturnType( @@ -649,6 +671,66 @@ func (agg *stMakeLineAgg) Size() int64 { return sizeOfSTMakeLineAggregate } +type stUnionAgg struct { + srid geopb.SRID + // TODO(#geo): store the current union object in C memory, to avoid the EWKB round trips. + ewkb geopb.EWKB + set bool +} + +// Add implements the AggregateFunc interface. +func (agg *stUnionAgg) Add(_ context.Context, firstArg tree.Datum, otherArgs ...tree.Datum) error { + if firstArg == tree.DNull { + return nil + } + geomArg := tree.MustBeDGeometry(firstArg) + if !agg.set { + agg.ewkb = geomArg.EWKB() + agg.set = true + agg.srid = geomArg.SRID() + return nil + } + if agg.srid != geomArg.SRID() { + c, err := geo.ParseGeometryFromEWKB(agg.ewkb) + if err != nil { + return err + } + return geo.NewMismatchingSRIDsError(geomArg.Geometry, c) + } + var err error + // TODO(#geo):We are allocating a slice for the result each time we + // call geos.Union in cStringToSafeGoBytes. + // We could change geos.Union to accept the existing slice. + agg.ewkb, err = geos.Union(agg.ewkb, geomArg.EWKB()) + return err +} + +// Result implements the AggregateFunc interface. +func (agg *stUnionAgg) Result() (tree.Datum, error) { + if !agg.set { + return tree.DNull, nil + } + g, err := geo.ParseGeometryFromEWKB(agg.ewkb) + if err != nil { + return nil, err + } + return tree.NewDGeometry(g), nil +} + +// Reset implements the AggregateFunc interface. +func (agg *stUnionAgg) Reset(context.Context) { + agg.ewkb = nil + agg.set = false +} + +// Close implements the AggregateFunc interface. +func (agg *stUnionAgg) Close(context.Context) {} + +// Size implements the AggregateFunc interface. +func (agg *stUnionAgg) Size() int64 { + return sizeOfSTUnionAggregate +} + type stExtentAgg struct { bbox *geo.CartesianBoundingBox } @@ -739,6 +821,7 @@ var _ tree.AggregateFunc = &bitBitOrAggregate{} var _ tree.AggregateFunc = &percentileDiscAggregate{} var _ tree.AggregateFunc = &percentileContAggregate{} var _ tree.AggregateFunc = &stMakeLineAgg{} +var _ tree.AggregateFunc = &stUnionAgg{} var _ tree.AggregateFunc = &stExtentAgg{} const sizeOfArrayAggregate = int64(unsafe.Sizeof(arrayAggregate{})) @@ -779,6 +862,7 @@ const sizeOfBitBitOrAggregate = int64(unsafe.Sizeof(bitBitOrAggregate{})) const sizeOfPercentileDiscAggregate = int64(unsafe.Sizeof(percentileDiscAggregate{})) const sizeOfPercentileContAggregate = int64(unsafe.Sizeof(percentileContAggregate{})) const sizeOfSTMakeLineAggregate = int64(unsafe.Sizeof(stMakeLineAgg{})) +const sizeOfSTUnionAggregate = int64(unsafe.Sizeof(stUnionAgg{})) const sizeOfSTExtentAggregate = int64(unsafe.Sizeof(stExtentAgg{})) // singleDatumAggregateBase is a utility struct that helps aggregate builtins diff --git a/pkg/sql/sem/builtins/geo_builtins.go b/pkg/sql/sem/builtins/geo_builtins.go index feae50678d10..f781ca18a90a 100644 --- a/pkg/sql/sem/builtins/geo_builtins.go +++ b/pkg/sql/sem/builtins/geo_builtins.go @@ -778,6 +778,140 @@ var geoBuiltins = map[string]builtinDefinition{ Volatility: tree.VolatilityImmutable, }, ), + "st_pointfromgeohash": makeBuiltin( + defProps(), + tree.Overload{ + Types: tree.ArgTypes{ + {"geohash", types.String}, + {"precision", types.Int}, + }, + ReturnType: tree.FixedReturnType(types.Geometry), + Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { + g := args[0].(*tree.DString) + p := args[1].(*tree.DInt) + ret, err := geo.ParseGeometryPointFromGeoHash(string(*g), int(*p)) + if err != nil { + return nil, err + } + return tree.NewDGeometry(ret), nil + }, + Info: infoBuilder{ + info: "Return a POINT Geometry from a GeoHash string with supplied precision.", + }.String(), + Volatility: tree.VolatilityImmutable, + }, + tree.Overload{ + Types: tree.ArgTypes{ + {"geohash", types.String}, + }, + ReturnType: tree.FixedReturnType(types.Geometry), + Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { + g := args[0].(*tree.DString) + p := len(string(*g)) + ret, err := geo.ParseGeometryPointFromGeoHash(string(*g), p) + if err != nil { + return nil, err + } + return tree.NewDGeometry(ret), nil + }, + Info: infoBuilder{ + info: "Return a POINT Geometry from a GeoHash string with max precision.", + }.String(), + Volatility: tree.VolatilityImmutable, + }, + ), + "st_geomfromgeohash": makeBuiltin( + defProps(), + tree.Overload{ + Types: tree.ArgTypes{ + {"geohash", types.String}, + {"precision", types.Int}, + }, + ReturnType: tree.FixedReturnType(types.Geometry), + Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { + g := args[0].(*tree.DString) + p := args[1].(*tree.DInt) + bbox, err := geo.ParseCartesianBoundingBoxFromGeoHash(string(*g), int(*p)) + if err != nil { + return nil, err + } + ret, err := geo.NewGeometryFromGeomT(bbox.ToGeomT()) + if err != nil { + return nil, err + } + return tree.NewDGeometry(ret), nil + }, + Info: infoBuilder{ + info: "Return a POLYGON Geometry from a GeoHash string with supplied precision.", + }.String(), + Volatility: tree.VolatilityImmutable, + }, + tree.Overload{ + Types: tree.ArgTypes{ + {"geohash", types.String}, + }, + ReturnType: tree.FixedReturnType(types.Geometry), + Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { + g := args[0].(*tree.DString) + p := len(string(*g)) + bbox, err := geo.ParseCartesianBoundingBoxFromGeoHash(string(*g), p) + if err != nil { + return nil, err + } + ret, err := geo.NewGeometryFromGeomT(bbox.ToGeomT()) + if err != nil { + return nil, err + } + return tree.NewDGeometry(ret), nil + }, + Info: infoBuilder{ + info: "Return a POLYGON Geometry from a GeoHash string with max precision.", + }.String(), + Volatility: tree.VolatilityImmutable, + }, + ), + "st_box2dfromgeohash": makeBuiltin( + defProps(), + tree.Overload{ + Types: tree.ArgTypes{ + {"geohash", types.String}, + {"precision", types.Int}, + }, + ReturnType: tree.FixedReturnType(types.Box2D), + Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { + g := args[0].(*tree.DString) + p := args[1].(*tree.DInt) + bbox, err := geo.ParseCartesianBoundingBoxFromGeoHash(string(*g), int(*p)) + if err != nil { + return nil, err + } + return tree.NewDBox2D(bbox), nil + }, + Info: infoBuilder{ + info: "Return a Box2D from a GeoHash string with supplied precision.", + }.String(), + Volatility: tree.VolatilityImmutable, + }, + tree.Overload{ + Types: tree.ArgTypes{ + {"geohash", types.String}, + }, + ReturnType: tree.FixedReturnType(types.Box2D), + Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { + g := args[0].(*tree.DString) + p := len(string(*g)) + bbox, err := geo.ParseCartesianBoundingBoxFromGeoHash(string(*g), p) + if err != nil { + return nil, err + } + return tree.NewDBox2D(bbox), nil + }, + Info: infoBuilder{ + info: "Return a Box2D from a GeoHash string with max precision.", + }.String(), + Volatility: tree.VolatilityImmutable, + }, + ), // // Output @@ -1177,48 +1311,6 @@ var geoBuiltins = map[string]builtinDefinition{ Volatility: tree.VolatilityImmutable, }, ), - "st_pointfromgeohash": makeBuiltin( - defProps(), - tree.Overload{ - Types: tree.ArgTypes{ - {"geohash", types.String}, - {"precision", types.Int}, - }, - ReturnType: tree.FixedReturnType(types.Geometry), - Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { - g := args[0].(*tree.DString) - p := args[1].(*tree.DInt) - ret, err := geo.NewGeometryPointFromGeoHash(string(*g), int(*p)) - if err != nil { - return nil, err - } - return tree.NewDGeometry(ret), nil - }, - Info: infoBuilder{ - info: "Return a Geometry point from a GeoHash string with supplied precision.", - }.String(), - Volatility: tree.VolatilityImmutable, - }, - tree.Overload{ - Types: tree.ArgTypes{ - {"geohash", types.String}, - }, - ReturnType: tree.FixedReturnType(types.Geometry), - Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { - g := args[0].(*tree.DString) - p := len(string(*g)) - ret, err := geo.NewGeometryPointFromGeoHash(string(*g), p) - if err != nil { - return nil, err - } - return tree.NewDGeometry(ret), nil - }, - Info: infoBuilder{ - info: "Return a Geometry point from a GeoHash string with max precision.", - }.String(), - Volatility: tree.VolatilityImmutable, - }, - ), "st_asgeojson": makeBuiltin( defProps(), tree.Overload{ @@ -2951,24 +3043,6 @@ For flags=1, validity considers self-intersecting rings forming holes as valid a tree.VolatilityImmutable, ), ), - "st_union": makeBuiltin( - defProps(), - geometryOverload2( - func(ctx *tree.EvalContext, a *tree.DGeometry, b *tree.DGeometry) (tree.Datum, error) { - union, err := geomfn.Union(a.Geometry, b.Geometry) - if err != nil { - return nil, err - } - return tree.NewDGeometry(union), err - }, - types.Geometry, - infoBuilder{ - info: "Returns the union of the given geometries as a single Geometry object.", - libraryUsage: usesGEOS, - }, - tree.VolatilityImmutable, - ), - ), // // Transformations diff --git a/pkg/sql/sqlliveness/slinstance/slinstance.go b/pkg/sql/sqlliveness/slinstance/slinstance.go index 5d85b0a86e9d..0cdcb7969bc9 100644 --- a/pkg/sql/sqlliveness/slinstance/slinstance.go +++ b/pkg/sql/sqlliveness/slinstance/slinstance.go @@ -42,7 +42,7 @@ var ( DefaultHeartBeat = settings.RegisterNonNegativeDurationSetting( "server.sqlliveness.heartbeat", "duration heart beats to push session expiration further out in time", - time.Second, + 5*time.Second, ) ) diff --git a/pkg/sql/sqlliveness/slprovider/slprovider.go b/pkg/sql/sqlliveness/slprovider/slprovider.go index f07eccea5fbc..72582b35dc90 100644 --- a/pkg/sql/sqlliveness/slprovider/slprovider.go +++ b/pkg/sql/sqlliveness/slprovider/slprovider.go @@ -17,10 +17,10 @@ import ( "github.com/cockroachdb/cockroach/pkg/kv" "github.com/cockroachdb/cockroach/pkg/settings/cluster" - "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/sql/sqlliveness" "github.com/cockroachdb/cockroach/pkg/sql/sqlliveness/slinstance" "github.com/cockroachdb/cockroach/pkg/sql/sqlliveness/slstorage" + "github.com/cockroachdb/cockroach/pkg/sql/sqlutil" "github.com/cockroachdb/cockroach/pkg/util/hlc" "github.com/cockroachdb/cockroach/pkg/util/metric" "github.com/cockroachdb/cockroach/pkg/util/stop" @@ -31,7 +31,7 @@ func New( stopper *stop.Stopper, clock *hlc.Clock, db *kv.DB, - ie tree.InternalExecutor, + ie sqlutil.InternalExecutor, settings *cluster.Settings, ) sqlliveness.Provider { storage := slstorage.NewStorage(stopper, clock, db, ie, settings) diff --git a/pkg/sql/sqlliveness/slstorage/slstorage.go b/pkg/sql/sqlliveness/slstorage/slstorage.go index f96ac29be7dc..d9e0d4f57bcd 100644 --- a/pkg/sql/sqlliveness/slstorage/slstorage.go +++ b/pkg/sql/sqlliveness/slstorage/slstorage.go @@ -12,13 +12,17 @@ package slstorage import ( "context" + "math/rand" "time" "github.com/cockroachdb/cockroach/pkg/kv" + "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/settings" "github.com/cockroachdb/cockroach/pkg/settings/cluster" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" "github.com/cockroachdb/cockroach/pkg/sql/sqlliveness" + "github.com/cockroachdb/cockroach/pkg/sql/sqlutil" "github.com/cockroachdb/cockroach/pkg/util/cache" "github.com/cockroachdb/cockroach/pkg/util/hlc" "github.com/cockroachdb/cockroach/pkg/util/log" @@ -29,12 +33,28 @@ import ( "github.com/cockroachdb/errors" ) -// DefaultGCInterval specifies duration between attempts to delete extant +// GCInterval specifies duration between attempts to delete extant // sessions that have expired. -var DefaultGCInterval = settings.RegisterNonNegativeDurationSetting( +var GCInterval = settings.RegisterNonNegativeDurationSetting( "server.sqlliveness.gc_interval", "duration between attempts to delete extant sessions that have expired", - time.Second, + 20*time.Second, +) + +// GCJitter specifies the jitter fraction on the interval between attempts to +// delete extant sessions that have expired. +// +// [(1-GCJitter) * GCInterval, (1+GCJitter) * GCInterval] +var GCJitter = settings.RegisterValidatedFloatSetting( + "server.sqlliveness.gc_jitter", + "jitter fraction on the duration between attempts to delete extant sessions that have expired", + .15, + func(f float64) error { + if f < 0 || f > 1 { + return errors.Errorf("%f is not in [0, 1]", f) + } + return nil + }, ) // CacheSize is the size of the entries to store in the cache. @@ -54,10 +74,12 @@ type Storage struct { stopper *stop.Stopper clock *hlc.Clock db *kv.DB - ex tree.InternalExecutor + ex sqlutil.InternalExecutor metrics Metrics gcInterval func() time.Duration g singleflight.Group + sd sqlbase.InternalExecutorSessionDataOverride + newTimer func() timeutil.TimerI mu struct { syncutil.RWMutex @@ -73,13 +95,16 @@ type Storage struct { } } -// NewStorage creates a new storage struct. -func NewStorage( +// NewTestingStorage constructs a new storage with control for the database +// in which the `sqlliveness` table should exist. +func NewTestingStorage( stopper *stop.Stopper, clock *hlc.Clock, db *kv.DB, - ie tree.InternalExecutor, + ie sqlutil.InternalExecutor, settings *cluster.Settings, + database string, + newTimer func() timeutil.TimerI, ) *Storage { s := &Storage{ settings: settings, @@ -87,8 +112,16 @@ func NewStorage( clock: clock, db: db, ex: ie, + sd: sqlbase.InternalExecutorSessionDataOverride{ + User: security.NodeUser, + Database: database, + }, + newTimer: newTimer, gcInterval: func() time.Duration { - return DefaultGCInterval.Get(&settings.SV) + baseInterval := GCInterval.Get(&settings.SV) + jitter := GCJitter.Get(&settings.SV) + frac := 1 + (2*rand.Float64()-1)*jitter + return time.Duration(frac * float64(baseInterval.Nanoseconds())) }, metrics: makeMetrics(), } @@ -103,6 +136,18 @@ func NewStorage( return s } +// NewStorage creates a new storage struct. +func NewStorage( + stopper *stop.Stopper, + clock *hlc.Clock, + db *kv.DB, + ie sqlutil.InternalExecutor, + settings *cluster.Settings, +) *Storage { + return NewTestingStorage(stopper, clock, db, ie, settings, "system", + timeutil.DefaultTimeSource{}.NewTimer) +} + // Metrics returns the associated metrics struct. func (s *Storage) Metrics() *Metrics { return &s.metrics @@ -123,39 +168,38 @@ func (s *Storage) Start(ctx context.Context) { // true, the session may no longer be alive, but if it returns false, the // session definitely is not alive. func (s *Storage) IsAlive(ctx context.Context, sid sqlliveness.SessionID) (alive bool, err error) { - // TODO(ajwerner): consider creating a zero-allocation cache key by converting - // the bytes to a string using unsafe. s.mu.RLock() if _, ok := s.mu.deadSessions.Get(sid); ok { s.mu.RUnlock() s.metrics.IsAliveCacheHits.Inc(1) return false, nil } + var prevExpiration hlc.Timestamp if expiration, ok := s.mu.liveSessions.Get(sid); ok { expiration := expiration.(hlc.Timestamp) - // The record exists but is expired. If we returned that the session was - // alive regardless of the expiration then we'd never update the cache. - // - // TODO(ajwerner): Utilize a rangefeed for the session state to update - // cache entries and always rely on the currently cached value. This - // approach may lead to lots of request in the period of time when a - // session is expired but has not yet been removed. Alternatively, this - // code could trigger deleteSessionsLoop or could use some other mechanism - // to wait for deleteSessionsLoop. + // The record exists and is valid. if s.clock.Now().Less(expiration) { s.mu.RUnlock() s.metrics.IsAliveCacheHits.Inc(1) return true, nil } + // The record exists in the cache but seems expired according to our clock. + // If we returned that the session was alive regardless of the expiration + // then we'd never update the cache. Go fetch the session and pass in the + // current view of the expiration. If the expiration has not changed, then + // the session is expired and should be deleted. If it has, get the new + // expiration for the cache. + prevExpiration = expiration } - // Launch singleflight to go read from the database. If it is found, we - // can add it and its expiration to the liveSessions cache. If it isn't - // found, we know it's dead and we can add that to the deadSessions cache. + // Launch singleflight to go read from the database and maybe delete the + // entry. If it is found, we can add it and its expiration to the liveSessions + // cache. If it isn't found, we know it's dead and we can add that to the + // deadSessions cache. resChan, _ := s.g.DoChan(string(sid), func() (interface{}, error) { // store the result underneath the singleflight to avoid the need // for additional synchronization. - live, expiration, err := s.fetchSession(ctx, sid) + live, expiration, err := s.deleteOrFetchSession(ctx, sid, prevExpiration) if err != nil { return nil, err } @@ -164,6 +208,7 @@ func (s *Storage) IsAlive(ctx context.Context, sid sqlliveness.SessionID) (alive if live { s.mu.liveSessions.Add(sid, expiration) } else { + s.mu.deadSessions.Del(sid) s.mu.deadSessions.Add(sid, nil) } return live, nil @@ -177,31 +222,50 @@ func (s *Storage) IsAlive(ctx context.Context, sid sqlliveness.SessionID) (alive return res.Val.(bool), nil } -// fetchSessions returns whether the query session currently exists by reading -// from the database. If the record exists, the associated expiration will be -// returned. -func (s *Storage) fetchSession( - ctx context.Context, sid sqlliveness.SessionID, +// deleteOrFetchSession returns whether the query session currently exists by +// reading from the database. If passed expiration is non-zero and the existing +// record has the same expiration, the record will be deleted and false will +// be returning, indicating that it no longer exists. If the record exists and +// has a differring expiration timestamp, true and the associated expiration +// will be returned. +func (s *Storage) deleteOrFetchSession( + ctx context.Context, sid sqlliveness.SessionID, prevExpiration hlc.Timestamp, ) (alive bool, expiration hlc.Timestamp, err error) { - var row tree.Datums - if err := s.db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) (err error) { - row, err = s.ex.QueryRow( - ctx, "expire-single-session", txn, ` -SELECT expiration FROM system.sqlliveness WHERE session_id = $1`, sid.UnsafeBytes(), - ) - return errors.Wrapf(err, "Could not query session id: %s", sid) + if err := s.db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { + + row, err := s.ex.QueryRowEx(ctx, "fetch-single-session", txn, s.sd, ` +SELECT expiration FROM sqlliveness WHERE session_id = $1 +`, sid.UnsafeBytes()) + if err != nil { + return err + } + + // The session is not alive. + if row == nil { + return nil + } + + // The session is alive if the read expiration differs from prevExpiration. + expiration, err = tree.DecimalToHLC(&row[0].(*tree.DDecimal).Decimal) + if err != nil { + return errors.Wrapf(err, "failed to parse expiration for session") + } + if !expiration.Equal(prevExpiration) { + alive = true + return nil + } + + // The session is expired and needs to be deleted. + expiration = hlc.Timestamp{} + _, err = s.ex.ExecEx(ctx, "delete-expired-session", txn, s.sd, ` +DELETE FROM sqlliveness WHERE session_id = $1 +`, sid.UnsafeBytes()) + return err }); err != nil { - return false, hlc.Timestamp{}, err + return false, hlc.Timestamp{}, errors.Wrapf(err, + "Could not query session id: %s", sid) } - if row == nil { - return false, hlc.Timestamp{}, nil - } - ts := row[0].(*tree.DDecimal) - exp, err := tree.DecimalToHLC(&ts.Decimal) - if err != nil { - return false, hlc.Timestamp{}, errors.Wrapf(err, "failed to parse expiration for session") - } - return true, exp, nil + return alive, expiration, nil } // deleteSessionsLoop is launched in start and periodically deletes sessions. @@ -209,28 +273,32 @@ func (s *Storage) deleteSessionsLoop(ctx context.Context) { ctx, cancel := s.stopper.WithCancelOnQuiesce(ctx) defer cancel() sqlliveness.WaitForActive(ctx, s.settings) - t := timeutil.NewTimer() - t.Reset(0) + t := s.newTimer() + t.Reset(s.gcInterval()) for { - if t.Read { - t.Reset(s.gcInterval()) - } select { case <-ctx.Done(): return - case <-t.C: - t.Read = true + case <-t.Ch(): + t.MarkRead() s.deleteExpiredSessions(ctx) + t.Reset(s.gcInterval()) } } } +// TODO(ajwerner): find a way to utilize this table scan to update the +// expirations stored in the in-memory cache or remove it altogether. As it +// stand, this scan will run more frequently than sessions expire but it won't +// propagate that fact to IsAlive. It seems like the lazy session deletion +// which has been added should be sufficient to delete expired sessions which +// matter. This would closer align with the behavior in node-liveness. func (s *Storage) deleteExpiredSessions(ctx context.Context) { now := s.clock.Now() - row, err := s.ex.QueryRow(ctx, "delete-sessions", nil, /* txn */ + row, err := s.ex.QueryRowEx(ctx, "delete-sessions", nil /* txn */, s.sd, ` WITH deleted_sessions AS ( - DELETE FROM system.sqlliveness + DELETE FROM sqlliveness WHERE expiration < $1 RETURNING session_id ) @@ -261,9 +329,9 @@ func (s *Storage) Insert( ctx context.Context, sid sqlliveness.SessionID, expiration hlc.Timestamp, ) (err error) { if err := s.db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { - _, err := s.ex.QueryRow( - ctx, "insert-session", txn, - `INSERT INTO system.sqlliveness VALUES ($1, $2)`, + _, err := s.ex.QueryRowEx( + ctx, "insert-session", txn, s.sd, + `INSERT INTO sqlliveness VALUES ($1, $2)`, sid.UnsafeBytes(), tree.TimestampToDecimalDatum(expiration), ) return err @@ -282,9 +350,9 @@ func (s *Storage) Update( ctx context.Context, sid sqlliveness.SessionID, expiration hlc.Timestamp, ) (sessionExists bool, err error) { err = s.db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { - data, err := s.ex.QueryRow( - ctx, "update-session", txn, ` -UPDATE system.sqlliveness SET expiration = $1 WHERE session_id = $2 RETURNING session_id`, + data, err := s.ex.QueryRowEx( + ctx, "update-session", txn, s.sd, ` +UPDATE sqlliveness SET expiration = $1 WHERE session_id = $2 RETURNING session_id`, tree.TimestampToDecimalDatum(expiration), sid.UnsafeBytes(), ) if err != nil { diff --git a/pkg/sql/sqlliveness/slstorage/slstorage_test.go b/pkg/sql/sqlliveness/slstorage/slstorage_test.go index 1fe479b1a755..3bee66101a17 100644 --- a/pkg/sql/sqlliveness/slstorage/slstorage_test.go +++ b/pkg/sql/sqlliveness/slstorage/slstorage_test.go @@ -12,71 +12,278 @@ package slstorage_test import ( "context" + "strings" "testing" "time" "github.com/cockroachdb/cockroach/pkg/base" "github.com/cockroachdb/cockroach/pkg/settings/cluster" - "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" - "github.com/cockroachdb/cockroach/pkg/sql/sqlliveness" + "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" "github.com/cockroachdb/cockroach/pkg/sql/sqlliveness/slstorage" + "github.com/cockroachdb/cockroach/pkg/sql/sqlutil" + "github.com/cockroachdb/cockroach/pkg/testutils" "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" + "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" + "github.com/cockroachdb/cockroach/pkg/util/hlc" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/cockroachdb/cockroach/pkg/util/log" + "github.com/cockroachdb/cockroach/pkg/util/stop" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/errors" "github.com/stretchr/testify/require" ) -func TestSQLStorage(t *testing.T) { +func TestStorage(t *testing.T) { defer leaktest.AfterTest(t)() defer log.Scope(t).Close(t) ctx := context.Background() - // Start the server such that it effectively never GC's records so that - // we can instantiate another Storage instance which we can control. - serverSettings := cluster.MakeTestingClusterSettings() - slstorage.DefaultGCInterval.Override(&serverSettings.SV, 24*time.Hour) - s, _, _ := serverutils.StartServer(t, base.TestServerArgs{ - Settings: serverSettings, - }) + s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) defer s.Stopper().Stop(ctx) + ie := s.InternalExecutor().(sqlutil.InternalExecutor) + tDB := sqlutils.MakeSQLRunner(sqlDB) + t0 := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) + + setup := func(t *testing.T) ( + *hlc.Clock, *timeutil.ManualTime, *cluster.Settings, *stop.Stopper, *slstorage.Storage, + ) { + dbName := t.Name() + tDB.Exec(t, `CREATE DATABASE "`+dbName+`"`) + schema := strings.Replace(sqlbase.SqllivenessTableSchema, + `CREATE TABLE system.sqlliveness`, + `CREATE TABLE "`+dbName+`".sqlliveness`, 1) + tDB.Exec(t, schema) + + timeSource := timeutil.NewManualTime(t0) + clock := hlc.NewClock(func() int64 { + return timeSource.Now().UnixNano() + }, base.DefaultMaxClockOffset) + settings := cluster.MakeTestingClusterSettings() + stopper := stop.NewStopper() + storage := slstorage.NewTestingStorage(stopper, clock, kvDB, ie, settings, + dbName, timeSource.NewTimer) + return clock, timeSource, settings, stopper, storage + } + + t.Run("basic-insert-is-alive", func(t *testing.T) { + clock, _, _, stopper, storage := setup(t) + defer stopper.Stop(ctx) + + exp := clock.Now().Add(time.Second.Nanoseconds(), 0) + const id = "asdf" + metrics := storage.Metrics() + + { + require.NoError(t, storage.Insert(ctx, id, exp)) + require.Equal(t, int64(1), metrics.WriteSuccesses.Count()) + } + { + isAlive, err := storage.IsAlive(ctx, id) + require.NoError(t, err) + require.True(t, isAlive) + require.Equal(t, int64(1), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(0), metrics.IsAliveCacheHits.Count()) + } + { + isAlive, err := storage.IsAlive(ctx, id) + require.NoError(t, err) + require.True(t, isAlive) + require.Equal(t, int64(1), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(1), metrics.IsAliveCacheHits.Count()) + } + }) + t.Run("delete-update", func(t *testing.T) { + clock, timeSource, settings, stopper, storage := setup(t) + defer stopper.Stop(ctx) + slstorage.GCJitter.Override(&settings.SV, 0) + storage.Start(ctx) + metrics := storage.Metrics() + + // GC will run some time after startup. + gcInterval := slstorage.GCInterval.Get(&settings.SV) + nextGC := timeSource.Now().Add(gcInterval) + testutils.SucceedsSoon(t, func() error { + timers := timeSource.Timers() + if len(timers) != 1 { + return errors.Errorf("expected 1 timer, saw %d", len(timers)) + } + require.Equal(t, []time.Time{nextGC}, timers) + return nil + }) + require.Equal(t, int64(0), metrics.SessionDeletionsRuns.Count()) + + // Create two records which will expire before nextGC. + exp := clock.Now().Add(gcInterval.Nanoseconds()-1, 0) + const id1 = "asdf" + const id2 = "ghjk" + { + require.NoError(t, storage.Insert(ctx, id1, exp)) + require.NoError(t, storage.Insert(ctx, id2, exp)) + require.Equal(t, int64(2), metrics.WriteSuccesses.Count()) + } + + // Verify they are alive. + { + isAlive1, err := storage.IsAlive(ctx, id1) + require.NoError(t, err) + require.True(t, isAlive1) + isAlive2, err := storage.IsAlive(ctx, id2) + require.NoError(t, err) + require.True(t, isAlive2) + require.Equal(t, int64(2), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(0), metrics.IsAliveCacheHits.Count()) + } - // Wait for our server which roughly never runs deletion runs to run its - // initial run. - serverLivenessProvider := s.SQLLivenessProvider().(sqlliveness.Provider) - require.Eventually(t, func() bool { - return serverLivenessProvider.Metrics().(*slstorage.Metrics).SessionDeletionsRuns.Count() > 0 - }, 5*time.Second, time.Millisecond) - - // Now construct a new storage which we can control. We won't start it just - // yet. - settings := cluster.MakeTestingClusterSettings() - slstorage.DefaultGCInterval.Override(&settings.SV, 1*time.Microsecond) - ie := s.InternalExecutor().(tree.InternalExecutor) - slStorage := slstorage.NewStorage(s.Stopper(), s.Clock(), s.DB(), ie, settings) - - const sid = "1" - err := slStorage.Insert(ctx, sid, s.Clock().Now()) - require.NoError(t, err) - metrics := slStorage.Metrics() - require.Equal(t, int64(1), metrics.WriteSuccesses.Count()) - - // Start the new Storage and wait for it delete our session which expired - // immediately. - slStorage.Start(ctx) - require.Eventually(t, func() bool { - a, err := slStorage.IsAlive(ctx, sid) - return !a && err == nil - }, 2*time.Second, 10*time.Millisecond) - log.Infof(ctx, "wtf mate") - require.Eventually(t, func() bool { - return metrics.SessionsDeleted.Count() == int64(1) - }, time.Second, time.Millisecond, metrics.SessionsDeleted.Count()) - require.True(t, metrics.SessionDeletionsRuns.Count() >= 1, - metrics.SessionDeletionsRuns.Count()) - - // Ensure that the update to the session failed. - found, err := slStorage.Update(ctx, sid, s.Clock().Now()) - require.NoError(t, err) - require.False(t, found) - require.Equal(t, int64(1), metrics.WriteFailures.Count()) + // Update the expiration for id2. + { + exists, err := storage.Update(ctx, id2, hlc.Timestamp{WallTime: nextGC.UnixNano() + 1}) + require.NoError(t, err) + require.True(t, exists) + require.Equal(t, int64(3), metrics.WriteSuccesses.Count()) + } + + // Ensure that the cached value is still in use for id2. + { + isAlive, err := storage.IsAlive(ctx, id2) + require.NoError(t, err) + require.True(t, isAlive) + require.Equal(t, int64(2), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(1), metrics.IsAliveCacheHits.Count()) + } + + // Advance time to nextGC, wait for there to be a new timer. + timeSource.Advance(gcInterval) + followingGC := nextGC.Add(gcInterval) + testutils.SucceedsSoon(t, func() error { + timers := timeSource.Timers() + if len(timers) != 1 { + return errors.Errorf("expected 1 timer, saw %d", len(timers)) + } + if timers[0].Equal(followingGC) { + return nil + } + return errors.Errorf("expected %v, saw %v", followingGC, timers[0]) + }) + // Ensure that we saw the second gc run and the deletion. + require.Equal(t, int64(1), metrics.SessionDeletionsRuns.Count()) + require.Equal(t, int64(1), metrics.SessionsDeleted.Count()) + + // Ensure that we now see the id1 as dead. + { + isAlive, err := storage.IsAlive(ctx, id1) + require.NoError(t, err) + require.False(t, isAlive) + require.Equal(t, int64(3), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(1), metrics.IsAliveCacheHits.Count()) + } + // Ensure that the fact that it's dead is cached. + { + isAlive, err := storage.IsAlive(ctx, id1) + require.NoError(t, err) + require.False(t, isAlive) + require.Equal(t, int64(3), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(2), metrics.IsAliveCacheHits.Count()) + } + // Ensure that attempts to update the now dead session fail. + { + exists, err := storage.Update(ctx, id1, hlc.Timestamp{WallTime: nextGC.UnixNano() + 1}) + require.NoError(t, err) + require.False(t, exists) + require.Equal(t, int64(1), metrics.WriteFailures.Count()) + } + + // Ensure that we now see the id2 as alive. + { + isAlive, err := storage.IsAlive(ctx, id2) + require.NoError(t, err) + require.True(t, isAlive) + require.Equal(t, int64(4), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(2), metrics.IsAliveCacheHits.Count()) + } + // Ensure that the fact that it's still alive is cached. + { + isAlive, err := storage.IsAlive(ctx, id1) + require.NoError(t, err) + require.False(t, isAlive) + require.Equal(t, int64(4), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(3), metrics.IsAliveCacheHits.Count()) + } + }) + t.Run("delete-expired-on-is-alive", func(t *testing.T) { + clock, timeSource, _, stopper, storage := setup(t) + defer stopper.Stop(ctx) + + exp := clock.Now().Add(time.Second.Nanoseconds(), 0) + const id = "asdf" + metrics := storage.Metrics() + + { + require.NoError(t, storage.Insert(ctx, id, exp)) + require.Equal(t, int64(1), metrics.WriteSuccesses.Count()) + } + { + isAlive, err := storage.IsAlive(ctx, id) + require.NoError(t, err) + require.True(t, isAlive) + require.Equal(t, int64(1), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(0), metrics.IsAliveCacheHits.Count()) + } + // Advance to the point where the session is expired. + timeSource.Advance(time.Second + time.Nanosecond) + // Ensure that we discover it is no longer alive. + { + isAlive, err := storage.IsAlive(ctx, id) + require.NoError(t, err) + require.False(t, isAlive) + require.Equal(t, int64(2), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(0), metrics.IsAliveCacheHits.Count()) + } + // Ensure that the fact that it is no longer alive is cached. + { + isAlive, err := storage.IsAlive(ctx, id) + require.NoError(t, err) + require.False(t, isAlive) + require.Equal(t, int64(2), metrics.IsAliveCacheMisses.Count()) + require.Equal(t, int64(1), metrics.IsAliveCacheHits.Count()) + } + // Ensure it cannot be updated. + { + exists, err := storage.Update(ctx, id, exp.Add(time.Second.Nanoseconds(), 0)) + require.NoError(t, err) + require.False(t, exists) + require.Equal(t, int64(1), metrics.WriteFailures.Count()) + } + }) + t.Run("test-jitter", func(t *testing.T) { + // We want to test that the GC runs a number of times but is jitterred. + _, timeSource, settings, stopper, storage := setup(t) + defer stopper.Stop(ctx) + storage.Start(ctx) + + waitForGCTimer := func() (timer time.Time) { + testutils.SucceedsSoon(t, func() error { + timers := timeSource.Timers() + if len(timers) != 1 { + return errors.Errorf("expected 1 timer, saw %d", len(timers)) + } + timer = timers[0] + return nil + }) + return timer + } + const N = 10 + for i := 0; i < N; i++ { + timer := waitForGCTimer() + timeSource.Advance(timer.Sub(timeSource.Now())) + } + jitter := slstorage.GCJitter.Get(&settings.SV) + interval := slstorage.GCInterval.Get(&settings.SV) + minTime := t0.Add(time.Duration((1 - jitter) * float64(interval.Nanoseconds()) * N)) + maxTime := t0.Add(time.Duration((1 + jitter) * float64(interval.Nanoseconds()) * N)) + noJitterTime := t0.Add(interval * N) + now := timeSource.Now() + require.Truef(t, now.After(minTime), "%v > %v", now, minTime) + require.Truef(t, now.Before(maxTime), "%v < %v", now, maxTime) + require.Truef(t, !now.Equal(noJitterTime), "%v != %v", now, noJitterTime) + }) } diff --git a/pkg/util/quotapool/config.go b/pkg/util/quotapool/config.go index 35fb2bdca67f..54809151eb86 100644 --- a/pkg/util/quotapool/config.go +++ b/pkg/util/quotapool/config.go @@ -70,7 +70,7 @@ func (f optionFunc) apply(cfg *config) { f(cfg) } // WithTimeSource is used to configure a quotapool to use the provided // TimeSource. -func WithTimeSource(ts TimeSource) Option { +func WithTimeSource(ts timeutil.TimeSource) Option { return optionFunc(func(cfg *config) { cfg.timeSource = ts }) @@ -88,12 +88,12 @@ type config struct { onAcquisition AcquisitionFunc onSlowAcquisition SlowAcquisitionFunc slowAcquisitionThreshold time.Duration - timeSource TimeSource + timeSource timeutil.TimeSource closer <-chan struct{} } var defaultConfig = config{ - timeSource: defaultTimeSource{}, + timeSource: timeutil.DefaultTimeSource{}, } func initializeConfig(cfg *config, options ...Option) { diff --git a/pkg/util/quotapool/int_rate_test.go b/pkg/util/quotapool/int_rate_test.go index 64296ce5f370..cc735460889b 100644 --- a/pkg/util/quotapool/int_rate_test.go +++ b/pkg/util/quotapool/int_rate_test.go @@ -18,6 +18,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/testutils" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/cockroachdb/cockroach/pkg/util/quotapool" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/errors" "github.com/stretchr/testify/require" ) @@ -26,7 +27,7 @@ func TestRateLimiterBasic(t *testing.T) { defer leaktest.AfterTest(t)() t0 := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) - mt := quotapool.NewManualTime(t0) + mt := timeutil.NewManualTime(t0) rl := quotapool.NewRateLimiter("test", 10, 20, quotapool.WithTimeSource(mt)) ctx := context.Background() @@ -148,7 +149,7 @@ func TestRateLimiterWithVerySmallDelta(t *testing.T) { defer leaktest.AfterTest(t)() t0 := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) - mt := quotapool.NewManualTime(t0) + mt := timeutil.NewManualTime(t0) rl := quotapool.NewRateLimiter("test", 2e9, 1e10, quotapool.WithTimeSource(mt)) ctx := context.Background() diff --git a/pkg/util/quotapool/intpool_test.go b/pkg/util/quotapool/intpool_test.go index fe3bf965ae04..d198d9959894 100644 --- a/pkg/util/quotapool/intpool_test.go +++ b/pkg/util/quotapool/intpool_test.go @@ -25,6 +25,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/testutils" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/cockroachdb/cockroach/pkg/util/quotapool" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -821,7 +822,7 @@ func TestLogSlowAcquisition(t *testing.T) { defer leaktest.AfterTest(t)() t0 := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) - mt := quotapool.NewManualTime(t0) + mt := timeutil.NewManualTime(t0) var called, calledAfter int64 qp := quotapool.NewIntPool("test", 10, quotapool.OnSlowAcquisition(time.Second, func( @@ -885,7 +886,7 @@ func TestCloser(t *testing.T) { defer leaktest.AfterTest(t)() t0 := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) - mt := quotapool.NewManualTime(t0) + mt := timeutil.NewManualTime(t0) closer := make(chan struct{}) qp := quotapool.NewIntPool("test", 10, quotapool.WithCloser(closer), diff --git a/pkg/util/quotapool/quotapool.go b/pkg/util/quotapool/quotapool.go index 299454f44103..81932801b7dd 100644 --- a/pkg/util/quotapool/quotapool.go +++ b/pkg/util/quotapool/quotapool.go @@ -23,6 +23,7 @@ import ( "time" "github.com/cockroachdb/cockroach/pkg/util/syncutil" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" ) // TODO(ajwerner): provide option to limit the maximum queue size. @@ -139,7 +140,7 @@ func New(name string, initialResource Resource, options ...Option) *QuotaPool { } // TimeSource returns the TimeSource associated with this QuotaPool. -func (qp *QuotaPool) TimeSource() TimeSource { +func (qp *QuotaPool) TimeSource() timeutil.TimeSource { return qp.timeSource } @@ -232,7 +233,7 @@ func (qp *QuotaPool) Acquire(ctx context.Context, r Request) (err error) { } // Set up the infrastructure to report slow requests. - var slowTimer Timer + var slowTimer timeutil.TimerI var slowTimerC <-chan time.Time if qp.onSlowAcquisition != nil { slowTimer = qp.timeSource.NewTimer() @@ -245,7 +246,7 @@ func (qp *QuotaPool) Acquire(ctx context.Context, r Request) (err error) { // Set up the infrastructure to deal with rate-limiter style pools which // retry after the passage of time. - var tryAgainTimer Timer + var tryAgainTimer timeutil.TimerI var tryAgainTimerC <-chan time.Time stopTryAgainTimer := func() { if tryAgainTimer == nil { diff --git a/pkg/util/quotapool/time.go b/pkg/util/quotapool/time.go deleted file mode 100644 index 36408814d5fc..000000000000 --- a/pkg/util/quotapool/time.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -package quotapool - -import ( - "time" - - "github.com/cockroachdb/cockroach/pkg/util/timeutil" -) - -// TimeSource is used to interact with clocks and timers. Generally exposed for -// testing. -type TimeSource interface { - Now() time.Time - NewTimer() Timer -} - -// Timer is an interface wrapping timeutil.Timer. -type Timer interface { - Reset(duration time.Duration) - Stop() bool - Ch() <-chan time.Time - MarkRead() -} - -type defaultTimeSource struct{} - -var _ TimeSource = defaultTimeSource{} - -func (defaultTimeSource) Now() time.Time { - return timeutil.Now() -} - -func (d defaultTimeSource) NewTimer() Timer { - return (*timer)(timeutil.NewTimer()) -} - -type timer timeutil.Timer - -var _ Timer = (*timer)(nil) - -func (t *timer) Reset(duration time.Duration) { - (*timeutil.Timer)(t).Reset(duration) -} - -func (t *timer) Stop() bool { - return (*timeutil.Timer)(t).Stop() -} - -func (t *timer) Ch() <-chan time.Time { - return t.C -} - -func (t *timer) MarkRead() { - t.Read = true -} diff --git a/pkg/util/quotapool/manual_time.go b/pkg/util/timeutil/manual_time.go similarity index 97% rename from pkg/util/quotapool/manual_time.go rename to pkg/util/timeutil/manual_time.go index b6926e5a4948..aaddd0e3522a 100644 --- a/pkg/util/quotapool/manual_time.go +++ b/pkg/util/timeutil/manual_time.go @@ -8,7 +8,7 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. -package quotapool +package timeutil import ( "container/heap" @@ -47,7 +47,7 @@ func (m *ManualTime) Now() time.Time { } // NewTimer constructs a new Timer. -func (m *ManualTime) NewTimer() Timer { +func (m *ManualTime) NewTimer() TimerI { return &manualTimer{m: m} } @@ -152,7 +152,7 @@ type manualTimer struct { ch chan time.Time } -var _ Timer = (*manualTimer)(nil) +var _ TimerI = (*manualTimer)(nil) func (m *manualTimer) Reset(duration time.Duration) { m.Stop() diff --git a/pkg/util/quotapool/manual_time_test.go b/pkg/util/timeutil/manual_time_test.go similarity index 85% rename from pkg/util/quotapool/manual_time_test.go rename to pkg/util/timeutil/manual_time_test.go index 2300434ed70b..dd9fff2106d5 100644 --- a/pkg/util/quotapool/manual_time_test.go +++ b/pkg/util/timeutil/manual_time_test.go @@ -8,14 +8,14 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. -package quotapool_test +package timeutil_test import ( "testing" "time" "github.com/cockroachdb/cockroach/pkg/util/leaktest" - "github.com/cockroachdb/cockroach/pkg/util/quotapool" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/stretchr/testify/require" ) @@ -29,24 +29,24 @@ func TestManualTime(t *testing.T) { t5 := t0.Add(5 * time.Second) t.Run("Advance", func(t *testing.T) { - mt := quotapool.NewManualTime(t0) + mt := timeutil.NewManualTime(t0) require.Equal(t, t0, mt.Now()) mt.Advance(time.Second) require.Equal(t, t1, mt.Now()) }) t.Run("AdvanceTo", func(t *testing.T) { - mt := quotapool.NewManualTime(t0) + mt := timeutil.NewManualTime(t0) mt.AdvanceTo(t2) require.Equal(t, t2, mt.Now()) mt.AdvanceTo(t1) require.Equal(t, t2, mt.Now()) }) t.Run("Timer.Stop on unset", func(t *testing.T) { - mt := quotapool.NewManualTime(t0) + mt := timeutil.NewManualTime(t0) timer := mt.NewTimer() require.False(t, timer.Stop()) }) - ensureDontSend := func(t *testing.T, timers ...quotapool.Timer) { + ensureDontSend := func(t *testing.T, timers ...timeutil.TimerI) { for _, timer := range timers { select { case <-timer.Ch(): @@ -55,7 +55,7 @@ func TestManualTime(t *testing.T) { } } } - ensureSends := func(t *testing.T, timer quotapool.Timer) { + ensureSends := func(t *testing.T, timer timeutil.TimerI) { select { case <-timer.Ch(): default: @@ -63,13 +63,13 @@ func TestManualTime(t *testing.T) { } } t.Run("Timer basics", func(t *testing.T) { - mt := quotapool.NewManualTime(t0) - mkTimer := func(d time.Duration) quotapool.Timer { + mt := timeutil.NewManualTime(t0) + mkTimer := func(d time.Duration) timeutil.TimerI { timer := mt.NewTimer() timer.Reset(d) return timer } - timers := []quotapool.Timer{ + timers := []timeutil.TimerI{ mkTimer(0 * time.Second), mkTimer(1 * time.Second), mkTimer(2 * time.Second), diff --git a/pkg/util/timeutil/time_source.go b/pkg/util/timeutil/time_source.go new file mode 100644 index 000000000000..495c7224062f --- /dev/null +++ b/pkg/util/timeutil/time_source.go @@ -0,0 +1,73 @@ +// Copyright 2020 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package timeutil + +import "time" + +// TimeSource is used to interact with clocks and timers. Generally exposed for +// testing. +type TimeSource interface { + Now() time.Time + NewTimer() TimerI +} + +// TimerI is an interface wrapping Timer. +type TimerI interface { + + // Reset will set the timer to notify on Ch() after duration. + Reset(duration time.Duration) + + // Stop must only be called one time per timer. + Stop() bool + + // Ch returns the channel which will be notified when the timer reaches its + // time. + Ch() <-chan time.Time + + // MarkRead should be called when a value is read from the Ch() channel. + // If MarkRead is not called, the resetting the timer is less efficient. + MarkRead() +} + +// DefaultTimeSource is a TimeSource using the system clock. +type DefaultTimeSource struct{} + +var _ TimeSource = DefaultTimeSource{} + +// Now returns timeutil.Now(). +func (DefaultTimeSource) Now() time.Time { + return Now() +} + +// NewTimer returns a TimerI wrapping *Timer. +func (DefaultTimeSource) NewTimer() TimerI { + return (*timer)(NewTimer()) +} + +type timer Timer + +var _ TimerI = (*timer)(nil) + +func (t *timer) Reset(duration time.Duration) { + (*Timer)(t).Reset(duration) +} + +func (t *timer) Stop() bool { + return (*Timer)(t).Stop() +} + +func (t *timer) Ch() <-chan time.Time { + return t.C +} + +func (t *timer) MarkRead() { + t.Read = true +}