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: v23.1.8: relation × (67321): depends-on function × (67320) has no corresponding depended-on-by back reference #109414

Closed
cockroach-sentry opened this issue Aug 24, 2023 · 3 comments · Fixed by #110130
Assignees
Labels
C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. db-cy-23 O-sentry Originated from an in-the-wild panic report. T-sql-foundations SQL Foundations Team (formerly SQL Schema + SQL Sessions)

Comments

@cockroach-sentry
Copy link
Collaborator

cockroach-sentry commented Aug 24, 2023

This issue was auto filed by Sentry. It represents a crash or reported error on a live cluster with telemetry enabled.

Sentry Link: https://cockroach-labs.sentry.io/issues/4417277648/?referrer=webhooks_plugin

Panic Message:

validate.go:357: relation × (67321): depends-on function × (67320) has no corresponding depended-on-by back reference
(1) keys: [sql.schema.validation_errors.write.backward_references.relation]
Wraps: (2) keys: [sql.schema.validation_errors.write.backward_references.relation]
Wraps: (3) attached stack trace
  -- stack trace:
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate.(*validationErrorAccumulator).decorate
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate/validate.go:256
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate.(*validationErrorAccumulator).Report
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate/validate.go:186
  | [...repeated from below...]
Wraps: (4) relation × (67321)
Wraps: (5) assertion failure
Wraps: (6) attached stack trace
  -- stack trace:
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc.(*wrapper).validateOutboundFuncRefBackReferenceForConstraint
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc/validate.go:357
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc.(*wrapper).ValidateBackReferences
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc/validate.go:249
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate.Validate.func3
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate/validate.go:114
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate.(*validationErrorAccumulator).validateDescriptorsAtLevel
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate/validate.go:202
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate.Validate
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/internal/validate/validate.go:109
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).Validate
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/validate.go:40
  | github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).ValidateUncommittedDescriptors
  | 	github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/validate.go:74
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).commitSQLTransactionInternal
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor_exec.go:1330
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).commitSQLTransaction
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor_exec.go:1234
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execStmtInOpenState
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor_exec.go:768
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execStmt.func1
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor_exec.go:142
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execWithProfiling
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor_exec.go:2986
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execStmt
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor_exec.go:141
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execCmd.func1
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor.go:2181
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execCmd
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor.go:2186
  | github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).run
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor.go:2103
  | github.com/cockroachdb/cockroach/pkg/sql.(*Server).ServeConn
  | 	github.com/cockroachdb/cockroach/pkg/sql/conn_executor.go:900
  | github.com/cockroachdb/cockroach/pkg/sql/pgwire.(*conn).processCommandsAsync.func1
  | 	github.com/cockroachdb/cockroach/pkg/sql/pgwire/conn.go:310
  | runtime.goexit
  | 	src/runtime/asm_arm64.s:1172
Wraps: (7) depends-on function × (67320) has no corresponding depended-on-by back reference
Error types: (1) *telemetrykeys.withTelemetry (2) *telemetrykeys.withTelemetry (3) *withstack.withStack (4) *errutil.withPrefix (5) *assert.withAssertionFailure (6) *withstack.withStack (7) *errutil.leafError
-- report composition:
*errutil.leafError: depends-on function × (67320) has no corresponding depended-on-by back reference
validate.go:357: *withstack.withStack (top exception)
*assert.withAssertionFailure
*errutil.withPrefix: relation × (67321)
validate.go:256: *withstack.withStack (1)
*telemetrykeys.withTelemetry: sql.schema.validation_errors.write.backward_references.relation
*telemetrykeys.withTelemetry: sql.schema.validation_errors.write.backward_references.relation
(check the extra data payloads)
Stacktrace (expand for inline code snippets):

src/runtime/asm_arm64.s#L1171-L1173

reservedOwned = false // We're about to pass ownership away.
retErr = sqlServer.ServeConn(
ctx,

}(ctx, h)
return h.ex.run(ctx, s.pool, reserved, cancel)
}

var err error
if err = ex.execCmd(); err != nil {
// Both of these errors are normal ways for the connExecutor to exit.

return err
}()
// Note: we write to ex.statsCollector.PhaseTimes, instead of ex.phaseTimes,

tcmd.LastInBatch || !implicitTxnForBatch)
ev, payload, err = ex.execStmt(
ctx, tcmd.Statement, nil /* portal */, nil /* pinfo */, stmtRes, canAutoCommit,

}
err = ex.execWithProfiling(ctx, ast, preparedStmt, func(ctx context.Context) error {
ev, payload, err = ex.execStmtInOpenState(ctx, parserStmt, portal, pinfo, res, canAutoCommit)

} else {
err = op(ctx)
}

err = ex.execWithProfiling(ctx, ast, preparedStmt, func(ctx context.Context) error {
ev, payload, err = ex.execStmtInOpenState(ctx, parserStmt, portal, pinfo, res, canAutoCommit)
return err

// CommitTransaction is executed fully here; there's no plan for it.
ev, payload := ex.commitSQLTransaction(ctx, ast, ex.commitSQLTransactionInternal)
return ev, payload, nil

ex.phaseTimes.SetSessionPhaseTime(sessionphase.SessionStartTransactionCommit, timeutil.Now())
if err := commitFn(ctx); err != nil {
if descs.IsTwoVersionInvariantViolationError(err) {

ex.planner.execCfg)
if err := ex.extraTxnState.descCollection.ValidateUncommittedDescriptors(ctx, ex.state.mu.txn, ex.extraTxnState.validateDbZoneConfig, zoneConfigValidator); err != nil {
return err

}
if err := tc.Validate(ctx, txn, catalog.ValidationWriteTelemetry, validate.Write, descs...); err != nil {
return err

version := tc.settings.Version.ActiveVersion(ctx)
return validate.Validate(
ctx,

// Descriptor backward-reference checks.
if !vea.validateDescriptorsAtLevel(
catalog.ValidationLevelBackReferences,

vea.currentDescriptor = desc
validationFn(desc)
}

if !desc.Dropped() {
desc.ValidateBackReferences(&vea, vdg)
}

}
vea.Report(desc.validateOutboundFuncRefBackReferenceForConstraint(fn, cst.ConstraintID))
}

}
vea.errors = append(vea.errors, vea.decorate(err))
}

case catalog.Table:
err = errors.Wrapf(err, string(catalog.Table)+" %q (%d)", name, id)
case catalog.Database:

src/runtime/asm_arm64.s#L1171-L1173
reservedOwned = false // We're about to pass ownership away.
retErr = sqlServer.ServeConn(
ctx,

}(ctx, h)
return h.ex.run(ctx, s.pool, reserved, cancel)
}

var err error
if err = ex.execCmd(); err != nil {
// Both of these errors are normal ways for the connExecutor to exit.

return err
}()
// Note: we write to ex.statsCollector.PhaseTimes, instead of ex.phaseTimes,

tcmd.LastInBatch || !implicitTxnForBatch)
ev, payload, err = ex.execStmt(
ctx, tcmd.Statement, nil /* portal */, nil /* pinfo */, stmtRes, canAutoCommit,

}
err = ex.execWithProfiling(ctx, ast, preparedStmt, func(ctx context.Context) error {
ev, payload, err = ex.execStmtInOpenState(ctx, parserStmt, portal, pinfo, res, canAutoCommit)

} else {
err = op(ctx)
}

err = ex.execWithProfiling(ctx, ast, preparedStmt, func(ctx context.Context) error {
ev, payload, err = ex.execStmtInOpenState(ctx, parserStmt, portal, pinfo, res, canAutoCommit)
return err

// CommitTransaction is executed fully here; there's no plan for it.
ev, payload := ex.commitSQLTransaction(ctx, ast, ex.commitSQLTransactionInternal)
return ev, payload, nil

ex.phaseTimes.SetSessionPhaseTime(sessionphase.SessionStartTransactionCommit, timeutil.Now())
if err := commitFn(ctx); err != nil {
if descs.IsTwoVersionInvariantViolationError(err) {

ex.planner.execCfg)
if err := ex.extraTxnState.descCollection.ValidateUncommittedDescriptors(ctx, ex.state.mu.txn, ex.extraTxnState.validateDbZoneConfig, zoneConfigValidator); err != nil {
return err

}
if err := tc.Validate(ctx, txn, catalog.ValidationWriteTelemetry, validate.Write, descs...); err != nil {
return err

version := tc.settings.Version.ActiveVersion(ctx)
return validate.Validate(
ctx,

// Descriptor backward-reference checks.
if !vea.validateDescriptorsAtLevel(
catalog.ValidationLevelBackReferences,

vea.currentDescriptor = desc
validationFn(desc)
}

if !desc.Dropped() {
desc.ValidateBackReferences(&vea, vdg)
}

}
vea.Report(desc.validateOutboundFuncRefBackReferenceForConstraint(fn, cst.ConstraintID))
}

}
return errors.AssertionFailedf("depends-on function %q (%d) has no corresponding depended-on-by back reference",
ref.GetName(), ref.GetID())

src/runtime/asm_arm64.s in runtime.goexit at line 1172
pkg/sql/pgwire/conn.go in pkg/sql/pgwire.(*conn).processCommandsAsync.func1 at line 310
pkg/sql/conn_executor.go in pkg/sql.(*Server).ServeConn at line 900
pkg/sql/conn_executor.go in pkg/sql.(*connExecutor).run at line 2103
pkg/sql/conn_executor.go in pkg/sql.(*connExecutor).execCmd at line 2186
pkg/sql/conn_executor.go in pkg/sql.(*connExecutor).execCmd.func1 at line 2181
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).execStmt at line 141
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).execWithProfiling at line 2986
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).execStmt.func1 at line 142
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).execStmtInOpenState at line 768
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).commitSQLTransaction at line 1234
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).commitSQLTransactionInternal at line 1330
pkg/sql/catalog/descs/validate.go in pkg/sql/catalog/descs.(*Collection).ValidateUncommittedDescriptors at line 74
pkg/sql/catalog/descs/validate.go in pkg/sql/catalog/descs.(*Collection).Validate at line 40
pkg/sql/catalog/internal/validate/validate.go in pkg/sql/catalog/internal/validate.Validate at line 109
pkg/sql/catalog/internal/validate/validate.go in pkg/sql/catalog/internal/validate.(*validationErrorAccumulator).validateDescriptorsAtLevel at line 202
pkg/sql/catalog/internal/validate/validate.go in pkg/sql/catalog/internal/validate.Validate.func3 at line 114
pkg/sql/catalog/tabledesc/validate.go in pkg/sql/catalog/tabledesc.(*wrapper).ValidateBackReferences at line 249
pkg/sql/catalog/internal/validate/validate.go in pkg/sql/catalog/internal/validate.(*validationErrorAccumulator).Report at line 186
pkg/sql/catalog/internal/validate/validate.go in pkg/sql/catalog/internal/validate.(*validationErrorAccumulator).decorate at line 256
src/runtime/asm_arm64.s in runtime.goexit at line 1172
pkg/sql/pgwire/conn.go in pkg/sql/pgwire.(*conn).processCommandsAsync.func1 at line 310
pkg/sql/conn_executor.go in pkg/sql.(*Server).ServeConn at line 900
pkg/sql/conn_executor.go in pkg/sql.(*connExecutor).run at line 2103
pkg/sql/conn_executor.go in pkg/sql.(*connExecutor).execCmd at line 2186
pkg/sql/conn_executor.go in pkg/sql.(*connExecutor).execCmd.func1 at line 2181
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).execStmt at line 141
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).execWithProfiling at line 2986
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).execStmt.func1 at line 142
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).execStmtInOpenState at line 768
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).commitSQLTransaction at line 1234
pkg/sql/conn_executor_exec.go in pkg/sql.(*connExecutor).commitSQLTransactionInternal at line 1330
pkg/sql/catalog/descs/validate.go in pkg/sql/catalog/descs.(*Collection).ValidateUncommittedDescriptors at line 74
pkg/sql/catalog/descs/validate.go in pkg/sql/catalog/descs.(*Collection).Validate at line 40
pkg/sql/catalog/internal/validate/validate.go in pkg/sql/catalog/internal/validate.Validate at line 109
pkg/sql/catalog/internal/validate/validate.go in pkg/sql/catalog/internal/validate.(*validationErrorAccumulator).validateDescriptorsAtLevel at line 202
pkg/sql/catalog/internal/validate/validate.go in pkg/sql/catalog/internal/validate.Validate.func3 at line 114
pkg/sql/catalog/tabledesc/validate.go in pkg/sql/catalog/tabledesc.(*wrapper).ValidateBackReferences at line 249
pkg/sql/catalog/tabledesc/validate.go in pkg/sql/catalog/tabledesc.(*wrapper).validateOutboundFuncRefBackReferenceForConstraint at line 357

Tags

Tag Value
Command start-single-node
Environment v23.1.8
Go Version go1.19.10
Platform linux arm64
Distribution CCL
Cockroach Release v23.1.8
Cockroach SHA 2c1d4af
# of CPUs 5
# of Goroutines 340

Jira issue: CRDB-30913

@cockroach-sentry cockroach-sentry added O-sentry Originated from an in-the-wild panic report. C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. labels Aug 24, 2023
@hendrikheil
Copy link

hendrikheil commented Aug 24, 2023

I think I caused this error 🔥

Maybe some context here helps: I was trying to use a custom function in a check constraint to basically emulate a foreign key constraint where the related table is based on a column in the table.

Imagine the table a has (account_type: string and account_id: uuid) the constraint would run a function that runs:

select (CASE
    WHEN _type = 'type_a' THEN (SELECT EXISTS(SELECT * FROM a_accounts WHERE id = _id))
    WHEN _type = 'type_b' THEN (SELECT EXISTS(SELECT * FROM b_accounts WHERE id = _id))
    ELSE false
 END)

@hendrikheil
Copy link

Got it to work by disabling the transaction that was constructed around my function creation and schema change query

@yuzefovich yuzefovich changed the title Sentry: validate.go:357: relation × (67321): depends-on function × (67320) has no corresponding depended-on-by back reference (1) keys: [sql.schema.validation_errors.write.backward_references.relati... sql: v23.1.8: relation × (67321): depends-on function × (67320) has no corresponding depended-on-by back reference Aug 25, 2023
@yuzefovich yuzefovich added this to Triage in SQL Foundations via automation Aug 25, 2023
@blathers-crl blathers-crl bot added the T-sql-foundations SQL Foundations Team (formerly SQL Schema + SQL Sessions) label Aug 25, 2023
@chrisseto
Copy link
Contributor

chrisseto commented Sep 5, 2023

Thanks for the context @hendrikheil! I don't think I would have been able to reproduce this without the example you gave. I can repro on 2c1d4af with the following snippet:

BEGIN;
CREATE TABLE accounts_a (id UUID NOT NULL);
CREATE TABLE accounts_b (id UUID NOT NULL);
CREATE TABLE a (
  account_id UUID NOT NULL,
	account_type TEXT NOT NULL
);
CREATE FUNCTION is_a_or_b(account_id UUID, account_type TEXT) RETURNS BOOL LANGUAGE SQL AS $$ SELECT (CASE
	WHEN account_type = 'type_a' THEN (SELECT EXISTS(SELECT * FROM accounts_a WHERE id = account_id))
	WHEN account_type = 'type_b' THEN (SELECT EXISTS(SELECT * FROM accounts_b WHERE id = account_id))
	ELSE false
END) $$;
ALTER TABLE a ADD CONSTRAINT is_a_or_b CHECK (is_a_or_b(account_id, account_type));
COMMIT;

Looks like the trick is referencing multiple tables within the UDF 😄

chrisseto added a commit to chrisseto/cockroach that referenced this issue Sep 6, 2023
Previously, `ALTER TABLE ... ADD CONSTRAINT` statements  that referenced
a UDF did not appropriately update UDFs' `DependedOnBy` field to
reference the table/constraint that utilized it. This would surface as
the validation error reported in cockroachdb#109414, `relation X: depends-on
function X has no corresponding depended-on-by back reference`. This
commit ensures that the back references are updated by copying a hook
from `CREATE TABLE`.

Epic: None
Fixes: cockroachdb#109414
Release note (bug fix): `ALTER TABLE ... ADD CONSTRAINT CHECK ...`
statements that utilize a UDF in the CHECK no longer cause a validation
error.
chrisseto added a commit to chrisseto/cockroach that referenced this issue Sep 12, 2023
Previously, `ALTER TABLE ... ADD CONSTRAINT` statements  that referenced
a UDF did not appropriately update UDFs' `DependedOnBy` field to
reference the table/constraint that utilized it. This would surface as
the validation error reported in cockroachdb#109414, `relation X: depends-on
function X has no corresponding depended-on-by back reference`. This
commit ensures that the back references are updated by copying a hook
from `CREATE TABLE`.

Epic: None
Fixes: cockroachdb#109414
Release note (bug fix): `ALTER TABLE ... ADD CONSTRAINT CHECK ...`
statements that utilize a UDF in the CHECK no longer cause a validation
error.
craig bot pushed a commit that referenced this issue Sep 15, 2023
110130: sql: update UDF references in `ALTER TABLE` r=rafiss a=chrisseto

Previously, `ALTER TABLE ... ADD CONSTRAINT` statements  that referenced a UDF did not appropriately update UDFs' `DependedOnBy` field to reference the table/constraint that utilized it. This would surface as the validation error reported in #109414, `relation X: depends-on function X has no corresponding depended-on-by back reference`. This commit ensures that the back references are updated by copying a hook from `CREATE TABLE`.

Epic: None
Fixes: #109414
Release note (bug fix): `ALTER TABLE ... ADD CONSTRAINT CHECK ...` statements that utilize a UDF in the CHECK no longer cause a validation error.

Co-authored-by: Chris Seto <chriskseto@gmail.com>
@craig craig bot closed this as completed in 13bcca9 Sep 15, 2023
SQL Foundations automation moved this from Triage to Done Sep 15, 2023
blathers-crl bot pushed a commit that referenced this issue Sep 15, 2023
Previously, `ALTER TABLE ... ADD CONSTRAINT` statements  that referenced
a UDF did not appropriately update UDFs' `DependedOnBy` field to
reference the table/constraint that utilized it. This would surface as
the validation error reported in #109414, `relation X: depends-on
function X has no corresponding depended-on-by back reference`. This
commit ensures that the back references are updated by copying a hook
from `CREATE TABLE`.

Epic: None
Fixes: #109414
Release note (bug fix): `ALTER TABLE ... ADD CONSTRAINT CHECK ...`
statements that utilize a UDF in the CHECK no longer cause a validation
error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. db-cy-23 O-sentry Originated from an in-the-wild panic report. T-sql-foundations SQL Foundations Team (formerly SQL Schema + SQL Sessions)
Projects
Development

Successfully merging a pull request may close this issue.

4 participants