code: def merge_sorted_blocks(
      blocks: List[Block], sort_key: "SortKey"
  ) -> Tuple[Block, BlockMetadata]:
      stats = BlockExecStats.builder()
      blocks = [b for b in blocks if b.num_rows > 0]
      if len(blocks) == 0:
          ret = ArrowBlockAccessor._empty_table()
      else:
          concat_and_sort = get_concat_and_sort_transform(
              DataContext.get_current()
          )
          ret = concat_and_sort(blocks, sort_key)
      return ret, ArrowBlockAccessor(ret).get_metadata(
          None, exec_stats=stats.build()
      )
  
imports: import collections
  import heapq
  import random
  from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Optional, Tuple, TypeVar, Union
  import numpy
  from ray._private.utils import _get_pyarrow_version
  from ray.air.constants import TENSOR_COLUMN_NAME
  from ray.data._internal.arrow_ops import transform_polars, transform_pyarrow
  from ray.data._internal.numpy_support import convert_udf_returns_to_numpy, is_valid_udf_return
  from ray.data._internal.table_block import TableBlockAccessor, TableBlockBuilder
  from ray.data._internal.util import _truncated_repr, find_partitions
  from ray.data.block import Block, BlockAccessor, BlockExecStats, BlockMetadata, KeyType, U
  from ray.data.context import DataContext
  from ray.data.row import TableRow
label_desc: Use image node_id 31 for calling the ArrowBlockAccessor obj's underlying member method code with example usage: obj.merge_sorted_blocks(blocks, sort_key) and returns: ret,  ArrowBlockAccessor