예제 #1
0
def _undo_remove_shard(shard_id, update_only=False):
    """Recreate the shard metadata.

    :param shard_id: The ID of the shard that was being removed.
    :param update_only: Only update the state store and skip adding range
                        checks.
    """
    if update_only:
        return
    group_id = Shards.fetch(shard_id).group_id
    try:
        SHARD_METADATA.create_shard_meta_data(group_id)
    except _errors.DatabaseError as error:
        #If the create fails, do not insert the metadata.
        return
    spec_handler = SHARDING_SPECIFICATION_HANDLER[shard_type]
    upper_bound = spec_handler.get_upper_bound(
        shard.lower_bound,
        shard_mapping_id,
        shard_type
    )
    SHARD_METADATA.insert_shard_meta_data(shard.shard_id,
                                        shard.lower_bound,
                                        upper_bound,
                                        group_id)
예제 #2
0
def _remove_shard(shard_id, update_only=False):
    """Remove the RANGE specification mapping represented by the current
    RANGE shard specification object.

    :param shard_id: The shard ID of the shard that needs to be removed.
    :param update_only: Only update the state store and skip adding range
                        checks.

    :return: True if the remove succeeded
            False if the query failed
    :raises: ShardingError if the shard id is not found,
        :       ShardingError if the shard is not disabled.
    """
    range_sharding_specification, shard, _, _ = \
        verify_and_fetch_shard(shard_id)
    if shard.state == "ENABLED":
        raise _errors.ShardingError(SHARD_NOT_DISABLED)
    #Stop the replication of the shard group with the global
    #group. Also clear the references of the master and the
    #slave group from the current group.
    #NOTE: When we do the stopping of the shard group
    #replication in shard remove we are actually just clearing
    #the references, since a shard cannot  be removed unless
    #it is disabled and when it is disabled the replication is
    #stopped but the references are not cleared.
    if not update_only:
        #The Group ID needs to be fetched before the sharding
        #information is removed.
        group_id = Shards.fetch(shard.shard_id).group_id
    _stop_shard_group_replication(shard_id, True)
    range_sharding_specification.remove()
    shard.remove()
    if not update_only:
        SHARD_METADATA.drop_shard_meta_data(group_id)
    _LOGGER.debug("Removed Shard (%s).", shard_id)
예제 #3
0
def _remove_shard(shard_id, update_only=False):
    """Remove the RANGE specification mapping represented by the current
    RANGE shard specification object.

    :param shard_id: The shard ID of the shard that needs to be removed.
    :param update_only: Only update the state store and skip adding range
                        checks.

    :return: True if the remove succeeded
            False if the query failed
    :raises: ShardingError if the shard id is not found,
        :       ShardingError if the shard is not disabled.
    """
    range_sharding_specification, shard, _, _ = \
        verify_and_fetch_shard(shard_id)
    if shard.state == "ENABLED":
        raise _errors.ShardingError(SHARD_NOT_DISABLED)
    #Stop the replication of the shard group with the global
    #group. Also clear the references of the master and the
    #slave group from the current group.
    #NOTE: When we do the stopping of the shard group
    #replication in shard remove we are actually just clearing
    #the references, since a shard cannot  be removed unless
    #it is disabled and when it is disabled the replication is
    #stopped but the references are not cleared.
    if not update_only:
        #The Group ID needs to be fetched before the sharding
        #information is removed.
        group_id = Shards.fetch(shard.shard_id).group_id
    _stop_shard_group_replication(shard_id,  True)
    range_sharding_specification.remove()
    shard.remove()
    if not update_only:
        SHARD_METADATA.drop_shard_meta_data(group_id)
    _LOGGER.debug("Removed Shard (%s).", shard_id)
예제 #4
0
def _add_shard_range_check(shard_mapping_id, shard_type):
    """Add the shard ranges in the metadata tables of the shards

    :param shard_mapping_id: The shard mapping ID of the shards for which
                            the metadata needs to be added.
    :param shard_type: The datatype of the sharding definition.
    """
    shard_list = SHARDING_SPECIFICATION_HANDLER[shard_type].list(shard_mapping_id)
    for shard in shard_list:
        group_id = Shards.fetch(shard.shard_id).group_id
        #The metadata has to be created before adding the ranges because
        #the global group might have still not replicated the schema to the
        #shard group. If the replication has still not happened, adding
        #the bounds will throw an error.
        SHARD_METADATA.create_shard_meta_data(group_id)
        spec_handler = SHARDING_SPECIFICATION_HANDLER[shard_type]
        upper_bound = spec_handler.get_upper_bound(
            shard.lower_bound,
            shard_mapping_id,
            shard_type
        )
        SHARD_METADATA.insert_shard_meta_data(shard.shard_id,
                                            shard.lower_bound,
                                            upper_bound,
                                            group_id)
예제 #5
0
def _lookup(lookup_arg, key,  hint):
    """Given a table name and a key return the servers of the Group where the
    shard of this table can be found

    :param lookup_arg: table name for "LOCAL" lookups
                Shard Mapping ID for "GLOBAL" lookups.
    :param key: The key value that needs to be looked up
    :param hint: A hint indicates if the query is LOCAL or GLOBAL

    :return: The servers of the Group that contains the range in which the
            key belongs.
    """
    VALID_HINTS = ('LOCAL',  'GLOBAL')
    hint = hint.upper()
    if hint not in VALID_HINTS:
        raise _errors.ShardingError(INVALID_SHARDING_HINT)

    group = None

    #Perform the lookup for the group contaning the lookup data.
    if hint == "GLOBAL":
        #Fetch the shard mapping object. In the case of GLOBAL lookups
        #the shard mapping ID is passed directly. In the case of "LOCAL"
        #lookups it is the table name that is passed.
        shard_mapping = ShardMapping.fetch_by_id(lookup_arg)
        if shard_mapping is None:
            raise _errors.ShardingError(
                SHARD_MAPPING_NOT_FOUND % (lookup_arg,  )
                )
        #GLOBAL lookups. There can be only one global group, hence using
        #shard_mapping[0] is safe.
        group = Group.fetch(shard_mapping[0].global_group)
    else:
        shard_mapping = ShardMapping.fetch(lookup_arg)
        if shard_mapping is None:
            raise _errors.ShardingError(TABLE_NAME_NOT_FOUND % (lookup_arg,  ))
        sharding_specification =\
            SHARDING_SPECIFICATION_HANDLER[shard_mapping.type_name].\
            lookup(key, shard_mapping.shard_mapping_id, shard_mapping.type_name)
        if sharding_specification is None:
            raise _errors.ShardingError(INVALID_SHARDING_KEY % (key,  ))
        shard = Shards.fetch(str(sharding_specification.shard_id))
        if shard.state == "DISABLED":
            raise _errors.ShardingError(SHARD_NOT_ENABLED)
        #group cannot be None since there is a foreign key on the group_id.
        #An exception will be thrown nevertheless.
        group = Group.fetch(shard.group_id)
        if group is None:
            raise _errors.ShardingError(SHARD_LOCATION_NOT_FOUND)

    ret = []
    #An empty list will be returned if the registered group has not
    #servers.
    for server in group.servers():
        ret.append([str(server.uuid), server.address,
                   group.master == server.uuid])
    return ret
예제 #6
0
def verify_and_fetch_shard(shard_id):
    """Find out if the shard_id exists and return the sharding specification for
    it. If it does not exist throw an exception.

    :param shard_id: The ID for the shard whose specification needs to be
                     fetched.

    :return: The sharding specification class representing the shard ID.

    :raises: ShardingError if the shard ID is not found.
    """
    #Here the underlying sharding specification might be a RANGE
    #or a HASH. The type of sharding specification is obtained from the
    #shard mapping.
    range_sharding_spec = RangeShardingSpecification.fetch(shard_id)
    if range_sharding_spec is None:
        raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id,  ))

    #Fetch the shard mappings and use them to find the type of sharding
    #scheme.
    shard_mappings = ShardMapping.fetch_by_id(
                        range_sharding_spec.shard_mapping_id
                    )
    if shard_mappings is None:
        raise _errors.ShardingError(
                    SHARD_MAPPING_NOT_FOUND % (
                        range_sharding_spec.shard_mapping_id,
                    )
                )

    #Fetch the shard mapping definition. There is only one shard mapping
    #definition associated with all of the shard mappings.
    shard_mapping_defn =  ShardMapping.fetch_shard_mapping_defn(
                        range_sharding_spec.shard_mapping_id
                    )
    if shard_mapping_defn is None:
        raise _errors.ShardingError(
                    SHARD_MAPPING_DEFN_NOT_FOUND % (
                        range_sharding_spec.shard_mapping_id,
                    )
                )

    shard = Shards.fetch(shard_id)
    if shard is None:
        raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id,  ))

    #Both of the shard_mappings retrieved will be of the same sharding
    #type. Hence it is safe to use one of them to retireve the sharding type.
    if shard_mappings[0].type_name == "HASH":
        return HashShardingSpecification.fetch(shard_id), \
            shard,  shard_mappings, shard_mapping_defn
    else:
        return range_sharding_spec, shard, shard_mappings, shard_mapping_defn
예제 #7
0
def _undo_add_shard_range_check(shard_mapping_id, shard_type):
    """Remove the shard ranges in the metadata tables of the shards

    :param shard_mapping_id: The shard mapping ID of the shards for which
                            the metadata needs to be added.
    :param shard_type: The datatype of the sharding definition.
    """
    shard_list = SHARDING_SPECIFICATION_HANDLER[shard_type].list(shard_mapping_id)
    for shard in shard_list:
        group_id = Shards.fetch(shard.shard_id).group_id
        SHARD_METADATA.delete_shard_meta_data(group_id, shard.shard_id)
        SHARD_METADATA.drop_shard_meta_data(group_id)
예제 #8
0
def _undo_add_shard_range_check(shard_mapping_id, shard_type):
    """Remove the shard ranges in the metadata tables of the shards

    :param shard_mapping_id: The shard mapping ID of the shards for which
                            the metadata needs to be added.
    :param shard_type: The datatype of the sharding definition.
    """
    shard_list = SHARDING_SPECIFICATION_HANDLER[shard_type].list(
        shard_mapping_id)
    for shard in shard_list:
        group_id = Shards.fetch(shard.shard_id).group_id
        SHARD_METADATA.delete_shard_meta_data(group_id, shard.shard_id)
        SHARD_METADATA.drop_shard_meta_data(group_id)
예제 #9
0
def _lookup(lookup_arg, key, hint):
    """Given a table name and a key return the servers of the Group where the
    shard of this table can be found

    :param lookup_arg: table name for "LOCAL" lookups
                Shard Mapping ID for "GLOBAL" lookups.
    :param key: The key value that needs to be looked up
    :param hint: A hint indicates if the query is LOCAL or GLOBAL

    :return: The servers of the Group that contains the range in which the
            key belongs.
    """
    VALID_HINTS = ('LOCAL', 'GLOBAL')
    hint = hint.upper()
    if hint not in VALID_HINTS:
        raise _errors.ShardingError(INVALID_SHARDING_HINT)

    group = None

    #Perform the lookup for the group contaning the lookup data.
    if hint == "GLOBAL":
        #Fetch the shard mapping object. In the case of GLOBAL lookups
        #the shard mapping ID is passed directly. In the case of "LOCAL"
        #lookups it is the table name that is passed.
        shard_mapping = ShardMapping.fetch_by_id(lookup_arg)
        if shard_mapping is None:
            raise _errors.ShardingError(SHARD_MAPPING_NOT_FOUND %
                                        (lookup_arg, ))
        #GLOBAL lookups. There can be only one global group, hence using
        #shard_mapping[0] is safe.
        group_id = shard_mapping[0].global_group
    else:
        shard_mapping = ShardMapping.fetch(lookup_arg)
        if shard_mapping is None:
            raise _errors.ShardingError(TABLE_NAME_NOT_FOUND % (lookup_arg, ))
        sharding_specification = \
            SHARDING_SPECIFICATION_HANDLER[shard_mapping.type_name].\
            lookup(key, shard_mapping.shard_mapping_id, shard_mapping.type_name)
        if sharding_specification is None:
            raise _errors.ShardingError(INVALID_SHARDING_KEY % (key, ))
        shard = Shards.fetch(str(sharding_specification.shard_id))
        if shard.state == "DISABLED":
            raise _errors.ShardingError(SHARD_NOT_ENABLED)
        #group cannot be None since there is a foreign key on the group_id.
        #An exception will be thrown nevertheless.
        group_id = shard.group_id

    return ServerLookups().execute(group_id=group_id)
예제 #10
0
def verify_and_fetch_shard(shard_id):
    """Find out if the shard_id exists and return the sharding specification for
    it. If it does not exist throw an exception.

    :param shard_id: The ID for the shard whose specification needs to be
                     fetched.

    :return: The sharding specification class representing the shard ID.

    :raises: ShardingError if the shard ID is not found.
    """
    #Here the underlying sharding specification might be a RANGE
    #or a HASH. The type of sharding specification is obtained from the
    #shard mapping.
    range_sharding_spec = RangeShardingSpecification.fetch(shard_id)
    if range_sharding_spec is None:
        raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, ))

    #Fetch the shard mappings and use them to find the type of sharding
    #scheme.
    shard_mappings = ShardMapping.fetch_by_id(
        range_sharding_spec.shard_mapping_id)
    if shard_mappings is None:
        raise _errors.ShardingError(SHARD_MAPPING_NOT_FOUND %
                                    (range_sharding_spec.shard_mapping_id, ))

    #Fetch the shard mapping definition. There is only one shard mapping
    #definition associated with all of the shard mappings.
    shard_mapping_defn = ShardMapping.fetch_shard_mapping_defn(
        range_sharding_spec.shard_mapping_id)
    if shard_mapping_defn is None:
        raise _errors.ShardingError(SHARD_MAPPING_DEFN_NOT_FOUND %
                                    (range_sharding_spec.shard_mapping_id, ))

    shard = Shards.fetch(shard_id)
    if shard is None:
        raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, ))

    #Both of the shard_mappings retrieved will be of the same sharding
    #type. Hence it is safe to use one of them to retireve the sharding type.
    if shard_mappings[0].type_name == "HASH":
        return HashShardingSpecification.fetch(shard_id), \
            shard,  shard_mappings, shard_mapping_defn
    else:
        return range_sharding_spec, shard, shard_mappings, shard_mapping_defn
예제 #11
0
def _undo_remove_shard(shard_id, update_only=False):
    """Recreate the shard metadata.

    :param shard_id: The ID of the shard that was being removed.
    :param update_only: Only update the state store and skip adding range
                        checks.
    """
    if update_only:
        return
    group_id = Shards.fetch(shard_id).group_id
    try:
        SHARD_METADATA.create_shard_meta_data(group_id)
    except _errors.DatabaseError as error:
        #If the create fails, do not insert the metadata.
        return
    spec_handler = SHARDING_SPECIFICATION_HANDLER[shard_type]
    upper_bound = spec_handler.get_upper_bound(shard.lower_bound,
                                               shard_mapping_id, shard_type)
    SHARD_METADATA.insert_shard_meta_data(shard.shard_id, shard.lower_bound,
                                          upper_bound, group_id)
예제 #12
0
def _add_shard_range_check(shard_mapping_id, shard_type):
    """Add the shard ranges in the metadata tables of the shards

    :param shard_mapping_id: The shard mapping ID of the shards for which
                            the metadata needs to be added.
    :param shard_type: The datatype of the sharding definition.
    """
    shard_list = SHARDING_SPECIFICATION_HANDLER[shard_type].list(
        shard_mapping_id)
    for shard in shard_list:
        group_id = Shards.fetch(shard.shard_id).group_id
        #The metadata has to be created before adding the ranges because
        #the global group might have still not replicated the schema to the
        #shard group. If the replication has still not happened, adding
        #the bounds will throw an error.
        SHARD_METADATA.create_shard_meta_data(group_id)
        spec_handler = SHARDING_SPECIFICATION_HANDLER[shard_type]
        upper_bound = spec_handler.get_upper_bound(shard.lower_bound,
                                                   shard_mapping_id,
                                                   shard_type)
        SHARD_METADATA.insert_shard_meta_data(shard.shard_id,
                                              shard.lower_bound, upper_bound,
                                              group_id)
예제 #13
0
def _check_shard_information(shard_id, destn_group_id, mysqldump_binary,
                             mysqlclient_binary, split_value, config_file, prune_limit, cmd,
                             update_only):
    """Verify the sharding information before starting a re-sharding operation.

    :param shard_id: The destination shard ID.
    :param destn_group_id: The Destination group ID.
    :param mysqldump_binary: The path to the mysqldump binary.
    :param mysqlclient_binary: The path to the mysqlclient binary.
    :param split_value: The point at which the sharding definition
                        should be split.
    :param config_file: The complete path to the fabric configuration
                        file.
    :param prune_limit: The number of DELETEs that should be
                        done in one batch.
    :param cmd: Indicates if it is a split or a move being executed.
    :param update_only: If the operation is a update only operation.
    """
    if not _services_utils.is_valid_binary(mysqldump_binary):
        raise _errors.ShardingError(
                _services_sharding.MYSQLDUMP_NOT_FOUND % mysqldump_binary)

    if not _services_utils.is_valid_binary(mysqlclient_binary):
        raise _errors.ShardingError(
                _services_sharding.MYSQLCLIENT_NOT_FOUND % mysqlclient_binary)

    if cmd == "SPLIT":
        range_sharding_spec, _, shard_mappings, _ = \
            _services_sharding.verify_and_fetch_shard(shard_id)
        upper_bound = \
            SHARDING_SPECIFICATION_HANDLER[shard_mappings[0].type_name].\
                        get_upper_bound(
                            range_sharding_spec.lower_bound,
                            range_sharding_spec.shard_mapping_id,
                            shard_mappings[0].type_name
                          )
        #If the underlying sharding scheme is a HASH. When a shard is split,
        #all the tables that are part of the shard, have the same sharding
        #scheme. All the shard mappings associated with this shard_id will be
        #of the same sharding type. Hence it is safe to use one of the shard
        #mappings.
        if shard_mappings[0].type_name == "HASH":
            if split_value is not None:
                raise _errors.ShardingError(
                    _services_sharding.NO_LOWER_BOUND_FOR_HASH_SHARDING
                )
            if  upper_bound is None:
                #While splitting a range, retrieve the next upper bound and
                #find the mid-point, in the case where the next upper_bound
                #is unavailable pick the maximum value in the set of values in
                #the shard.
                upper_bound = HashShardingSpecification.fetch_max_key(shard_id)

            #Calculate the split value.
            split_value = \
                SHARDING_DATATYPE_HANDLER[shard_mappings[0].type_name].\
                split_value(
                    range_sharding_spec.lower_bound,
                    upper_bound
                )
        elif split_value is not None:
            if not (SHARDING_DATATYPE_HANDLER[shard_mappings[0].type_name].\
                    is_valid_split_value(
                        split_value, range_sharding_spec.lower_bound,
                        upper_bound
                    )
                ):
                raise _errors.ShardingError(
                    _services_sharding.INVALID_LOWER_BOUND_VALUE %
                    (split_value, )
                )
        elif split_value is None:
            raise _errors.ShardingError(
                _services_sharding.SPLIT_VALUE_NOT_DEFINED
            )

    #Ensure that the group does not already contain a shard.
    if Shards.lookup_shard_id(destn_group_id) is not None:
        raise _errors.ShardingError(
            _services_sharding.SHARD_MOVE_DESTINATION_NOT_EMPTY %
            (destn_group_id, )
        )

    #Fetch the group information for the source shard that
    #needs to be moved.
    source_shard = Shards.fetch(shard_id)
    if source_shard is None:
        raise _errors.ShardingError(
            _services_sharding.SHARD_NOT_FOUND % (shard_id, ))

    #Fetch the group_id and the group that hosts the source shard.
    source_group_id = source_shard.group_id

    destn_group = Group.fetch(destn_group_id)
    if destn_group is None:
        raise _errors.ShardingError(
            _services_sharding.SHARD_GROUP_NOT_FOUND %
            (destn_group_id, ))

    if not update_only:
        _events.trigger_within_procedure(
            BACKUP_SOURCE_SHARD, shard_id, source_group_id, destn_group_id,
            mysqldump_binary, mysqlclient_binary, split_value, config_file,
            prune_limit, cmd, update_only
        )
    else:
        _events.trigger_within_procedure(
            SETUP_RESHARDING_SWITCH, shard_id, source_group_id, destn_group_id,
            split_value, prune_limit, cmd, update_only
        )
예제 #14
0
def _check_shard_information(shard_id, destn_group_id, mysqldump_binary,
                             mysqlclient_binary, split_value, config_file,
                             prune_limit, cmd, update_only):
    """Verify the sharding information before starting a re-sharding operation.

    :param shard_id: The destination shard ID.
    :param destn_group_id: The Destination group ID.
    :param mysqldump_binary: The path to the mysqldump binary.
    :param mysqlclient_binary: The path to the mysqlclient binary.
    :param split_value: The point at which the sharding definition
                        should be split.
    :param config_file: The complete path to the fabric configuration
                        file.
    :param prune_limit: The number of DELETEs that should be
                        done in one batch.
    :param cmd: Indicates if it is a split or a move being executed.
    :param update_only: If the operation is a update only operation.
    """
    if not _services_utils.is_valid_binary(mysqldump_binary):
        raise _errors.ShardingError(_services_sharding.MYSQLDUMP_NOT_FOUND %
                                    mysqldump_binary)

    if not _services_utils.is_valid_binary(mysqlclient_binary):
        raise _errors.ShardingError(_services_sharding.MYSQLCLIENT_NOT_FOUND %
                                    mysqlclient_binary)

    if cmd == "SPLIT":
        range_sharding_spec, _, shard_mappings, _ = \
            _services_sharding.verify_and_fetch_shard(shard_id)
        upper_bound = \
            SHARDING_SPECIFICATION_HANDLER[shard_mappings[0].type_name].\
                        get_upper_bound(
                            range_sharding_spec.lower_bound,
                            range_sharding_spec.shard_mapping_id,
                            shard_mappings[0].type_name
                          )
        #If the underlying sharding scheme is a HASH. When a shard is split,
        #all the tables that are part of the shard, have the same sharding
        #scheme. All the shard mappings associated with this shard_id will be
        #of the same sharding type. Hence it is safe to use one of the shard
        #mappings.
        if shard_mappings[0].type_name == "HASH":
            if split_value is not None:
                raise _errors.ShardingError(
                    _services_sharding.NO_LOWER_BOUND_FOR_HASH_SHARDING)
            if upper_bound is None:
                #While splitting a range, retrieve the next upper bound and
                #find the mid-point, in the case where the next upper_bound
                #is unavailable pick the maximum value in the set of values in
                #the shard.
                upper_bound = HashShardingSpecification.fetch_max_key(shard_id)

            #Calculate the split value.
            split_value = \
                SHARDING_DATATYPE_HANDLER[shard_mappings[0].type_name].\
                split_value(
                    range_sharding_spec.lower_bound,
                    upper_bound
                )
        elif split_value is not None:
            if not (SHARDING_DATATYPE_HANDLER[shard_mappings[0].type_name].\
                    is_valid_split_value(
                        split_value, range_sharding_spec.lower_bound,
                        upper_bound
                    )
                ):
                raise _errors.ShardingError(
                    _services_sharding.INVALID_LOWER_BOUND_VALUE %
                    (split_value, ))
        elif split_value is None:
            raise _errors.ShardingError(
                _services_sharding.SPLIT_VALUE_NOT_DEFINED)

    #Ensure that the group does not already contain a shard.
    if Shards.lookup_shard_id(destn_group_id) is not None:
        raise _errors.ShardingError(
            _services_sharding.SHARD_MOVE_DESTINATION_NOT_EMPTY %
            (destn_group_id, ))

    #Fetch the group information for the source shard that
    #needs to be moved.
    source_shard = Shards.fetch(shard_id)
    if source_shard is None:
        raise _errors.ShardingError(_services_sharding.SHARD_NOT_FOUND %
                                    (shard_id, ))

    #Fetch the group_id and the group that hosts the source shard.
    source_group_id = source_shard.group_id

    destn_group = Group.fetch(destn_group_id)
    if destn_group is None:
        raise _errors.ShardingError(_services_sharding.SHARD_GROUP_NOT_FOUND %
                                    (destn_group_id, ))

    if not update_only:
        _events.trigger_within_procedure(BACKUP_SOURCE_SHARD, shard_id,
                                         source_group_id, destn_group_id,
                                         mysqldump_binary, mysqlclient_binary,
                                         split_value, config_file, prune_limit,
                                         cmd, update_only)
    else:
        _events.trigger_within_procedure(SETUP_RESHARDING_SWITCH, shard_id,
                                         source_group_id, destn_group_id,
                                         split_value, prune_limit, cmd,
                                         update_only)