class TransportDropConstraintAction extends AbstractDDLTransportAction<DropConstraintRequest, AcknowledgedResponse> {

    private static final String ACTION_NAME = "internal:crate:sql/table/drop_constraint";
    private final NodeContext nodeContext;
    private final IndicesService indicesService;

    @Inject
    public TransportDropConstraintAction(TransportService transportService,
                                    ClusterService clusterService,
                                    IndicesService indicesService,
                                    ThreadPool threadPool,
                                    NodeContext nodeContext) {
        super(ACTION_NAME,
            transportService,
            clusterService,
            threadPool,
            DropConstraintRequest::new,
            AcknowledgedResponse::new,
            AcknowledgedResponse::new,
            "drop-constraint");
        this.nodeContext = nodeContext;
        this.indicesService = indicesService;
    }


    @Override
    public ClusterStateTaskExecutor<DropConstraintRequest> clusterStateTaskExecutor(DropConstraintRequest request) {<FILL_FUNCTION_BODY>}

    private boolean updateMapping(ClusterState currentState,
                                  Metadata.Builder metadataBuilder,
                                  DropConstraintRequest request) throws IOException {
        Index[] concreteIndices = resolveIndices(currentState, request.relationName().indexNameOrAlias());
        boolean updated = false;

        for (Index index : concreteIndices) {
            final IndexMetadata indexMetadata = currentState.metadata().getIndexSafe(index);

            Map<String, Object> currentSource = indexMetadata.mapping().sourceAsMap();

            updated |= removeConstraints(currentSource, List.of(request.constraintName()));

            MapperService mapperService = indicesService.createIndexMapperService(indexMetadata);

            mapperService.merge(currentSource, MapperService.MergeReason.MAPPING_UPDATE);
            DocumentMapper mapper = mapperService.documentMapper();

            IndexMetadata.Builder imBuilder = IndexMetadata.builder(indexMetadata);
            imBuilder.putMapping(new MappingMetadata(mapper.mappingSource())).mappingVersion(1 + imBuilder.mappingVersion());
            metadataBuilder.put(imBuilder); // implicitly increments metadata version.
        }
        return updated;
    }

    @Override
    public ClusterBlockException checkBlock(DropConstraintRequest request, ClusterState state) {
        return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
    }
}

        return new DDLClusterStateTaskExecutor<>() {
            @Override
            protected ClusterState execute(ClusterState currentState, DropConstraintRequest request) throws Exception {
                Metadata.Builder metadataBuilder = Metadata.builder(currentState.metadata());
                boolean updated = false;

                // Update template if table is partitioned
                String templateName = PartitionName.templateName(request.relationName().schema(), request.relationName().name());
                IndexTemplateMetadata indexTemplateMetadata = currentState.metadata().templates().get(templateName);

                if (indexTemplateMetadata != null) {
                    // Removal happens by key, value in the deepest map is not used.
                    Map<String, Object> mapToRemove = Map.of("_meta", Map.of("check_constraints", Map.of(request.constraintName(), "")));

                    IndexTemplateMetadata newIndexTemplateMetadata = DDLClusterStateHelpers.updateTemplate(
                        indexTemplateMetadata,
                        Collections.emptyMap(),
                        mapToRemove,
                        Settings.EMPTY,
                        IndexScopedSettings.DEFAULT_SCOPED_SETTINGS // Not used if new settings are empty
                    );
                    updated = true;
                    metadataBuilder.put(newIndexTemplateMetadata);
                }

                updated |= updateMapping(currentState, metadataBuilder, request);
                if (updated) {
                    // ensure the new table can still be parsed into a DocTableInfo to avoid breaking the table.
                    new DocTableInfoFactory(nodeContext).create(request.relationName(), currentState.metadata());
                    return ClusterState.builder(currentState).metadata(metadataBuilder).build();
                }
                return currentState;
            }
        };
    
<methods>public void <init>(java.lang.String, org.elasticsearch.transport.TransportService, org.elasticsearch.cluster.service.ClusterService, org.elasticsearch.threadpool.ThreadPool, Reader<io.crate.execution.ddl.tables.DropConstraintRequest>, Reader<org.elasticsearch.action.support.master.AcknowledgedResponse>, Function<java.lang.Boolean,org.elasticsearch.action.support.master.AcknowledgedResponse>, java.lang.String) ,public abstract ClusterStateTaskExecutor<io.crate.execution.ddl.tables.DropConstraintRequest> clusterStateTaskExecutor(io.crate.execution.ddl.tables.DropConstraintRequest) <variables>private final non-sealed Function<java.lang.Boolean,org.elasticsearch.action.support.master.AcknowledgedResponse> ackedResponseFunction,private final non-sealed Reader<org.elasticsearch.action.support.master.AcknowledgedResponse> reader,private final non-sealed java.lang.String source