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()

```

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)

{"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"}]}