You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: constraint.go
    path of file: ./repos/cockroach/pkg/sql/schemachanger/scexec/scmutationexec
    
    the code of the file until where you have to start completion: // Copyright 2022 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 scmutationexec

import (
	"context"

	"github.com/cockroachdb/cockroach/pkg/sql/catalog"
	"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
	"github.com/cockroachdb/cockroach/pkg/sql/cat
    
func (i *immediateVisitor) SetConstraintName(ctx context.Context, op scop.SetConstraintName) error {
	tbl, err := i.checkOutTable(ctx, op.TableID)
	if err != nil || tbl.Dropped() {
		return err
	}
	constraint, err := catalog.MustFindConstraintByID(tbl, op.ConstraintID)
	if err != nil {
		return err
	}
	if constraint.AsUniqueWithIndex() != nil {
		constraint.AsUniqueWithIndex().IndexDesc().Name = op.Name
	} else if constraint.AsUniqueWithoutIndex() != nil {
		constraint.AsUniqueWithoutIndex().UniqueWithoutIndexDesc().Name = op.Name
	} else if constraint.AsCheck() != nil {
		constraint.AsCheck().CheckDesc().Name = op.Name
	} else if constraint.AsForeignKey() != nil {
		oldName := constraint.AsForeignKey().ForeignKeyDesc().Name
		constraint.AsForeignKey().ForeignKeyDesc().Name = op.Name
		// Also attempt to set the FK constraint name in the referenced table.
		// This is needed on the dropping path (i.e. when dropping an existing
		// FK constraint).
		referencedTable, err := i.checkOutTable(ctx, constraint.AsForeignKey().GetReferencedTableID())
		if err != nil || referencedTable.Dropped() {
			return err
		}
		for _, inboundFK := range referencedTable.InboundForeignKeys() {
			// Unfortunately, because of a post-deserialization bug the IDs
			// between the origin and reference table may not properly sync in
			// restored descriptors. So, sadly we need to match by name when
			// updating names on the inbound side (TestRestoreOldVersions exposes this
			// scenario)
			if inboundFK.GetOriginTableID() == op.TableID && inboundFK.GetName() == oldName {
				inboundFK.ForeignKeyDesc().Name = op.Name
				break
			}
		}
	} else {
		return errors.AssertionFailedf("unknown constraint type")
	}
	return nil
}