Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: disallow using cluster_logical_timestamp as column default when backfilling #98696

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/sql/backfill/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ go_library(
"//pkg/sql/execinfra",
"//pkg/sql/execinfrapb",
"//pkg/sql/isql",
"//pkg/sql/pgwire/pgcode",
"//pkg/sql/pgwire/pgerror",
"//pkg/sql/row",
"//pkg/sql/rowenc",
"//pkg/sql/rowinfra",
Expand Down
12 changes: 12 additions & 0 deletions pkg/sql/backfill/backfill.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/catalog/typedesc"
"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
"github.com/cockroachdb/cockroach/pkg/sql/isql"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/sql/row"
"github.com/cockroachdb/cockroach/pkg/sql/rowenc"
"github.com/cockroachdb/cockroach/pkg/sql/rowinfra"
Expand Down Expand Up @@ -372,6 +374,11 @@ func (cb *ColumnBackfiller) RunColumnBackfillChunk(
for j, e := range cb.updateExprs {
val, err := eval.Expr(ctx, cb.evalCtx, e)
if err != nil {
if errors.Is(err, eval.ErrNilTxnInClusterContext) {
// Cannot use expressions that depend on the transaction of the
// evaluation context as the default value for backfill.
return roachpb.Key{}, pgerror.WithCandidateCode(err, pgcode.FeatureNotSupported)
}
return roachpb.Key{}, sqlerrors.NewInvalidSchemaDefinitionError(err)
}
if j < len(cb.added) && !cb.added[j].IsNullable() && val == tree.DNull {
Expand Down Expand Up @@ -876,6 +883,11 @@ func (ib *IndexBackfiller) BuildIndexEntriesChunk(
}
val, err := eval.Expr(ctx, ib.evalCtx, texpr)
if err != nil {
if errors.Is(err, eval.ErrNilTxnInClusterContext) {
// Cannot use expressions that depend on the transaction of the
// evaluation context as the default value for backfill.
err = pgerror.WithCandidateCode(err, pgcode.FeatureNotSupported)
}
return err
}
colIdx, ok := ib.colIdxMap.Get(colID)
Expand Down
11 changes: 11 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/alter_table
Original file line number Diff line number Diff line change
Expand Up @@ -3173,3 +3173,14 @@ SHOW CONSTRAINTS FROM t_96728
table_name constraint_name constraint_type details validated
t_96728 t_96728_j_k_key UNIQUE UNIQUE (j ASC, k ASC) WHERE (i > 0) true
t_96728 t_96728_pkey PRIMARY KEY PRIMARY KEY (i ASC) true

# This subtest disallows using builtin function `cluster_logical_timestamp()`
# as the default expression when backfilling a column.
subtest 98269

statement ok
CREATE TABLE t_98269 (i INT PRIMARY KEY);
INSERT INTO t_98269 VALUES (0);

statement error pgcode 0A000 .* cluster_logical_timestamp\(\): nil txn in cluster context
ALTER TABLE t_98269 ADD COLUMN j DECIMAL NOT NULL DEFAULT cluster_logical_timestamp();
2 changes: 1 addition & 1 deletion pkg/sql/sem/builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -2751,7 +2751,7 @@ nearest replica.`, builtinconstants.DefaultFollowerReadDuration),
Types: tree.ParamTypes{},
ReturnType: tree.FixedReturnType(types.Decimal),
Fn: func(ctx context.Context, evalCtx *eval.Context, args tree.Datums) (tree.Datum, error) {
return evalCtx.GetClusterTimestamp(), nil
return evalCtx.GetClusterTimestamp()
},
Info: `Returns the logical time of the current transaction as
a CockroachDB HLC in decimal form.
Expand Down
11 changes: 8 additions & 3 deletions pkg/sql/sem/eval/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ import (
"github.com/cockroachdb/errors"
)

var ErrNilTxnInClusterContext = errors.New("nil txn in cluster context")

// Context defines the context in which to evaluate an expression, allowing
// the retrieval of state such as the node ID or statement start time.
//
Expand Down Expand Up @@ -495,12 +497,15 @@ func (ec *Context) GetStmtTimestamp() time.Time {

// GetClusterTimestamp retrieves the current cluster timestamp as per
// the evaluation context. The timestamp is guaranteed to be nonzero.
func (ec *Context) GetClusterTimestamp() *tree.DDecimal {
func (ec *Context) GetClusterTimestamp() (*tree.DDecimal, error) {
if ec.Txn == nil {
return nil, ErrNilTxnInClusterContext
}
ts := ec.Txn.CommitTimestamp()
if ts.IsEmpty() {
panic(errors.AssertionFailedf("zero cluster timestamp in txn"))
return nil, errors.AssertionFailedf("zero cluster timestamp in txn")
}
return TimestampToDecimalDatum(ts)
return TimestampToDecimalDatum(ts), nil
}

// HasPlaceholders returns true if this EvalContext's placeholders have been
Expand Down
4 changes: 3 additions & 1 deletion pkg/sql/sem/eval/timeconv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/cockroach/pkg/util/stop"
"github.com/stretchr/testify/require"
)

// Test that EvalContext.GetClusterTimestamp() gets its timestamp from the
Expand Down Expand Up @@ -76,7 +77,8 @@ func TestClusterTimestampConversion(t *testing.T) {
),
}

dec := ctx.GetClusterTimestamp()
dec, err := ctx.GetClusterTimestamp()
require.NoError(t, err)
final := dec.Text('f')
if final != d.expected {
t.Errorf("expected %s, but found %s", d.expected, final)
Expand Down