prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  More informative IntegrityError on duplicate columns
  ```
  ~/Workspace/ibis/ibis/expr/schema.py in __init__(self, names, types)
       32 
       33         if len(self._name_locs) < len(self.names):
  ---> 34             raise com.IntegrityError('Duplicate column names')
       35 
       36     def __repr__(self):
  
  IntegrityError: Duplicate column names
  ```
  
  List the particular columns at least.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `ibis/expr/schema.py`
  Content:
  ```
  1 import collections
  2 
  3 from multipledispatch import Dispatcher
  4 
  5 import ibis.common.exceptions as com
  6 import ibis.expr.datatypes as dt
  7 import ibis.util as util
  8 
  9 
  10 class Schema:
  11 
  12     """An object for holding table schema information, i.e., column names and
  13     types.
  14 
  15     Parameters
  16     ----------
  17     names : Sequence[str]
  18         A sequence of ``str`` indicating the name of each column.
  19     types : Sequence[DataType]
  20         A sequence of :class:`ibis.expr.datatypes.DataType` objects
  21         representing type of each column.
  22     """
  23 
  24     __slots__ = 'names', 'types', '_name_locs'
  25 
  26     def __init__(self, names, types):
  27         if not isinstance(names, list):
  28             names = list(names)
  29 
  30         self.names = names
  31         self.types = list(map(dt.dtype, types))
  32 
  33         self._name_locs = dict((v, i) for i, v in enumerate(self.names))
  34 
  35         if len(self._name_locs) < len(self.names):
  36             raise com.IntegrityError('Duplicate column names')
  37 
  38     def __repr__(self):
  39         space = 2 + max(map(len, self.names), default=0)
  40         return "ibis.Schema {{{}\n}}".format(
  41             util.indent(
  42                 ''.join(
  43                     '\n{}{}'.format(name.ljust(space), str(type))
  44                     for name, type in zip(self.names, self.types)
  45                 ),
  46                 2,
  47             )
  48         )
  49 
  50     def __hash__(self):
  51         return hash((type(self), tuple(self.names), tuple(self.types)))
  52 
  53     def __len__(self):
  54         return len(self.names)
  55 
  56     def __iter__(self):
  57         return iter(self.names)
  58 
  59     def __contains__(self, name):
  60         return name in self._name_locs
  61 
  62     def __getitem__(self, name):
  63         return self.types[self._name_locs[name]]
  64 
  65     def __getstate__(self):
  66         return {slot: getattr(self, slot) for slot in self.__class__.__slots__}
  67 
  68     def __setstate__(self, instance_dict):
  69         for key, value in instance_dict.items():
  70             setattr(self, key, value)
  71 
  72     def delete(self, names_to_delete):
  73         for name in names_to_delete:
  74             if name not in self:
  75                 raise KeyError(name)
  76 
  77         new_names, new_types = [], []
  78         for name, type_ in zip(self.names, self.types):
  79             if name in names_to_delete:
  80                 continue
  81             new_names.append(name)
  82             new_types.append(type_)
  83 
  84         return Schema(new_names, new_types)
  85 
  86     @classmethod
  87     def from_tuples(cls, values):
  88         if not isinstance(values, (list, tuple)):
  89             values = list(values)
  90 
  91         names, types = zip(*values) if values else ([], [])
  92         return Schema(names, types)
  93 
  94     @classmethod
  95     def from_dict(cls, dictionary):
  96         return Schema(*zip(*dictionary.items()))
  97 
  98     def equals(self, other, cache=None):
  99         return self.names == other.names and self.types == other.types
  100 
  101     def __eq__(self, other):
  102         return self.equals(other)
  103 
  104     def __gt__(self, other):
  105         return set(self.items()) > set(other.items())
  106 
  107     def __ge__(self, other):
  108         return set(self.items()) >= set(other.items())
  109 
  110     def append(self, schema):
  111         return Schema(self.names + schema.names, self.types + schema.types)
  112 
  113     def items(self):
  114         return zip(self.names, self.types)
  115 
  116     def name_at_position(self, i):
  117         """
  118         """
  119         upper = len(self.names) - 1
  120         if not 0 <= i <= upper:
  121             raise ValueError(
  122                 'Column index must be between 0 and {:d}, inclusive'.format(
  123                     upper
  124                 )
  125             )
  126         return self.names[i]
  127 
  128 
  129 class HasSchema:
  130 
  131     """
  132     Base class representing a structured dataset with a well-defined
  133     schema.
  134 
  135     Base implementation is for tables that do not reference a particular
  136     concrete dataset or database table.
  137     """
  138 
  139     def __repr__(self):
  140         return '{}({})'.format(type(self).__name__, repr(self.schema))
  141 
  142     def has_schema(self):
  143         return True
  144 
  145     def equals(self, other, cache=None):
  146         return type(self) == type(other) and self.schema.equals(
  147             other.schema, cache=cache
  148         )
  149 
  150     def root_tables(self):
  151         return [self]
  152 
  153     @property
  154     def schema(self):
  155         raise NotImplementedError
  156 
  157 
  158 schema = Dispatcher('schema')
  159 infer = Dispatcher('infer')
  160 
  161 
  162 @schema.register(Schema)
  163 def identity(s):
  164     return s
  165 
  166 
  167 @schema.register(collections.abc.Mapping)
  168 def schema_from_mapping(d):
  169     return Schema.from_dict(d)
  170 
  171 
  172 @schema.register(collections.abc.Iterable)
  173 def schema_from_pairs(lst):
  174     return Schema.from_tuples(lst)
  175 
  176 
  177 @schema.register(collections.abc.Iterable, collections.abc.Iterable)
  178 def schema_from_names_types(names, types):
  179     return Schema(names, types)
  180
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/ibis/expr/schema.py b/ibis/expr/schema.py
  --- a/ibis/expr/schema.py
  +++ b/ibis/expr/schema.py
  @@ -33,7 +33,11 @@
           self._name_locs = dict((v, i) for i, v in enumerate(self.names))
   
           if len(self._name_locs) < len(self.names):
  -            raise com.IntegrityError('Duplicate column names')
  +            duplicate_names = list(self.names)
  +            for v in self._name_locs.keys():
  +                duplicate_names.remove(v)
  +            raise com.IntegrityError(
  +                'Duplicate column name(s): {}'.format(duplicate_names))
   
       def __repr__(self):
           space = 2 + max(map(len, self.names), default=0)
  
verification_info: {"golden_diff": "diff --git a/ibis/expr/schema.py b/ibis/expr/schema.py\n--- a/ibis/expr/schema.py\n+++ b/ibis/expr/schema.py\n@@ -33,7 +33,11 @@\n         self._name_locs = dict((v, i) for i, v in enumerate(self.names))\n \n         if len(self._name_locs) < len(self.names):\n-            raise com.IntegrityError('Duplicate column names')\n+            duplicate_names = list(self.names)\n+            for v in self._name_locs.keys():\n+                duplicate_names.remove(v)\n+            raise com.IntegrityError(\n+                'Duplicate column name(s): {}'.format(duplicate_names))\n \n     def __repr__(self):\n         space = 2 + max(map(len, self.names), default=0)\n", "issue": "More informative IntegrityError on duplicate columns\n```\r\n~/Workspace/ibis/ibis/expr/schema.py in __init__(self, names, types)\r\n     32 \r\n     33         if len(self._name_locs) < len(self.names):\r\n---> 34             raise com.IntegrityError('Duplicate column names')\r\n     35 \r\n     36     def __repr__(self):\r\n\r\nIntegrityError: Duplicate column names\r\n```\r\n\r\nList the particular columns at least.\n", "before_files": [{"content": "import collections\n\nfrom multipledispatch import Dispatcher\n\nimport ibis.common.exceptions as com\nimport ibis.expr.datatypes as dt\nimport ibis.util as util\n\n\nclass Schema:\n\n    \"\"\"An object for holding table schema information, i.e., column names and\n    types.\n\n    Parameters\n    ----------\n    names : Sequence[str]\n        A sequence of ``str`` indicating the name of each column.\n    types : Sequence[DataType]\n        A sequence of :class:`ibis.expr.datatypes.DataType` objects\n        representing type of each column.\n    \"\"\"\n\n    __slots__ = 'names', 'types', '_name_locs'\n\n    def __init__(self, names, types):\n        if not isinstance(names, list):\n            names = list(names)\n\n        self.names = names\n        self.types = list(map(dt.dtype, types))\n\n        self._name_locs = dict((v, i) for i, v in enumerate(self.names))\n\n        if len(self._name_locs) < len(self.names):\n            raise com.IntegrityError('Duplicate column names')\n\n    def __repr__(self):\n        space = 2 + max(map(len, self.names), default=0)\n        return \"ibis.Schema {{{}\\n}}\".format(\n            util.indent(\n                ''.join(\n                    '\\n{}{}'.format(name.ljust(space), str(type))\n                    for name, type in zip(self.names, self.types)\n                ),\n                2,\n            )\n        )\n\n    def __hash__(self):\n        return hash((type(self), tuple(self.names), tuple(self.types)))\n\n    def __len__(self):\n        return len(self.names)\n\n    def __iter__(self):\n        return iter(self.names)\n\n    def __contains__(self, name):\n        return name in self._name_locs\n\n    def __getitem__(self, name):\n        return self.types[self._name_locs[name]]\n\n    def __getstate__(self):\n        return {slot: getattr(self, slot) for slot in self.__class__.__slots__}\n\n    def __setstate__(self, instance_dict):\n        for key, value in instance_dict.items():\n            setattr(self, key, value)\n\n    def delete(self, names_to_delete):\n        for name in names_to_delete:\n            if name not in self:\n                raise KeyError(name)\n\n        new_names, new_types = [], []\n        for name, type_ in zip(self.names, self.types):\n            if name in names_to_delete:\n                continue\n            new_names.append(name)\n            new_types.append(type_)\n\n        return Schema(new_names, new_types)\n\n    @classmethod\n    def from_tuples(cls, values):\n        if not isinstance(values, (list, tuple)):\n            values = list(values)\n\n        names, types = zip(*values) if values else ([], [])\n        return Schema(names, types)\n\n    @classmethod\n    def from_dict(cls, dictionary):\n        return Schema(*zip(*dictionary.items()))\n\n    def equals(self, other, cache=None):\n        return self.names == other.names and self.types == other.types\n\n    def __eq__(self, other):\n        return self.equals(other)\n\n    def __gt__(self, other):\n        return set(self.items()) > set(other.items())\n\n    def __ge__(self, other):\n        return set(self.items()) >= set(other.items())\n\n    def append(self, schema):\n        return Schema(self.names + schema.names, self.types + schema.types)\n\n    def items(self):\n        return zip(self.names, self.types)\n\n    def name_at_position(self, i):\n        \"\"\"\n        \"\"\"\n        upper = len(self.names) - 1\n        if not 0 <= i <= upper:\n            raise ValueError(\n                'Column index must be between 0 and {:d}, inclusive'.format(\n                    upper\n                )\n            )\n        return self.names[i]\n\n\nclass HasSchema:\n\n    \"\"\"\n    Base class representing a structured dataset with a well-defined\n    schema.\n\n    Base implementation is for tables that do not reference a particular\n    concrete dataset or database table.\n    \"\"\"\n\n    def __repr__(self):\n        return '{}({})'.format(type(self).__name__, repr(self.schema))\n\n    def has_schema(self):\n        return True\n\n    def equals(self, other, cache=None):\n        return type(self) == type(other) and self.schema.equals(\n            other.schema, cache=cache\n        )\n\n    def root_tables(self):\n        return [self]\n\n    @property\n    def schema(self):\n        raise NotImplementedError\n\n\nschema = Dispatcher('schema')\ninfer = Dispatcher('infer')\n\n\n@schema.register(Schema)\ndef identity(s):\n    return s\n\n\n@schema.register(collections.abc.Mapping)\ndef schema_from_mapping(d):\n    return Schema.from_dict(d)\n\n\n@schema.register(collections.abc.Iterable)\ndef schema_from_pairs(lst):\n    return Schema.from_tuples(lst)\n\n\n@schema.register(collections.abc.Iterable, collections.abc.Iterable)\ndef schema_from_names_types(names, types):\n    return Schema(names, types)\n", "path": "ibis/expr/schema.py"}], "after_files": [{"content": "import collections\n\nfrom multipledispatch import Dispatcher\n\nimport ibis.common.exceptions as com\nimport ibis.expr.datatypes as dt\nimport ibis.util as util\n\n\nclass Schema:\n\n    \"\"\"An object for holding table schema information, i.e., column names and\n    types.\n\n    Parameters\n    ----------\n    names : Sequence[str]\n        A sequence of ``str`` indicating the name of each column.\n    types : Sequence[DataType]\n        A sequence of :class:`ibis.expr.datatypes.DataType` objects\n        representing type of each column.\n    \"\"\"\n\n    __slots__ = 'names', 'types', '_name_locs'\n\n    def __init__(self, names, types):\n        if not isinstance(names, list):\n            names = list(names)\n\n        self.names = names\n        self.types = list(map(dt.dtype, types))\n\n        self._name_locs = dict((v, i) for i, v in enumerate(self.names))\n\n        if len(self._name_locs) < len(self.names):\n            duplicate_names = list(self.names)\n            for v in self._name_locs.keys():\n                duplicate_names.remove(v)\n            raise com.IntegrityError(\n                'Duplicate column name(s): {}'.format(duplicate_names))\n\n    def __repr__(self):\n        space = 2 + max(map(len, self.names), default=0)\n        return \"ibis.Schema {{{}\\n}}\".format(\n            util.indent(\n                ''.join(\n                    '\\n{}{}'.format(name.ljust(space), str(type))\n                    for name, type in zip(self.names, self.types)\n                ),\n                2,\n            )\n        )\n\n    def __hash__(self):\n        return hash((type(self), tuple(self.names), tuple(self.types)))\n\n    def __len__(self):\n        return len(self.names)\n\n    def __iter__(self):\n        return iter(self.names)\n\n    def __contains__(self, name):\n        return name in self._name_locs\n\n    def __getitem__(self, name):\n        return self.types[self._name_locs[name]]\n\n    def __getstate__(self):\n        return {slot: getattr(self, slot) for slot in self.__class__.__slots__}\n\n    def __setstate__(self, instance_dict):\n        for key, value in instance_dict.items():\n            setattr(self, key, value)\n\n    def delete(self, names_to_delete):\n        for name in names_to_delete:\n            if name not in self:\n                raise KeyError(name)\n\n        new_names, new_types = [], []\n        for name, type_ in zip(self.names, self.types):\n            if name in names_to_delete:\n                continue\n            new_names.append(name)\n            new_types.append(type_)\n\n        return Schema(new_names, new_types)\n\n    @classmethod\n    def from_tuples(cls, values):\n        if not isinstance(values, (list, tuple)):\n            values = list(values)\n\n        names, types = zip(*values) if values else ([], [])\n        return Schema(names, types)\n\n    @classmethod\n    def from_dict(cls, dictionary):\n        return Schema(*zip(*dictionary.items()))\n\n    def equals(self, other, cache=None):\n        return self.names == other.names and self.types == other.types\n\n    def __eq__(self, other):\n        return self.equals(other)\n\n    def __gt__(self, other):\n        return set(self.items()) > set(other.items())\n\n    def __ge__(self, other):\n        return set(self.items()) >= set(other.items())\n\n    def append(self, schema):\n        return Schema(self.names + schema.names, self.types + schema.types)\n\n    def items(self):\n        return zip(self.names, self.types)\n\n    def name_at_position(self, i):\n        \"\"\"\n        \"\"\"\n        upper = len(self.names) - 1\n        if not 0 <= i <= upper:\n            raise ValueError(\n                'Column index must be between 0 and {:d}, inclusive'.format(\n                    upper\n                )\n            )\n        return self.names[i]\n\n\nclass HasSchema:\n\n    \"\"\"\n    Base class representing a structured dataset with a well-defined\n    schema.\n\n    Base implementation is for tables that do not reference a particular\n    concrete dataset or database table.\n    \"\"\"\n\n    def __repr__(self):\n        return '{}({})'.format(type(self).__name__, repr(self.schema))\n\n    def has_schema(self):\n        return True\n\n    def equals(self, other, cache=None):\n        return type(self) == type(other) and self.schema.equals(\n            other.schema, cache=cache\n        )\n\n    def root_tables(self):\n        return [self]\n\n    @property\n    def schema(self):\n        raise NotImplementedError\n\n\nschema = Dispatcher('schema')\ninfer = Dispatcher('infer')\n\n\n@schema.register(Schema)\ndef identity(s):\n    return s\n\n\n@schema.register(collections.abc.Mapping)\ndef schema_from_mapping(d):\n    return Schema.from_dict(d)\n\n\n@schema.register(collections.abc.Iterable)\ndef schema_from_pairs(lst):\n    return Schema.from_tuples(lst)\n\n\n@schema.register(collections.abc.Iterable, collections.abc.Iterable)\ndef schema_from_names_types(names, types):\n    return Schema(names, types)\n", "path": "ibis/expr/schema.py"}]}