Repository: duckdb/duckdb (language: python)

Issue:
The Parquet reader considers 'FOO' and 'foo' as duplicate column names when different cases are used for the column name and the partition key.
### What happens?

When a Parquet dataset contains a column names and a partition key which are case-sensitive different but case-insensitive the same, DuckDB fails when reading it.



### To Reproduce

1. Untar this file :
[people.tar.gz](https://github.com/user-attachments/files/18048196/people.tar.gz)

2. use the following SQL

```
.echo on

FROM read_parquet('people/**/*.parquet', hive_partitioning = false);
FROM read_parquet('people/**/*.parquet');
```

3. results : 

```
duckdb-1.1.3 < a.sql

FROM read_parquet('people/**/*.parquet', hive_partitioning = false);
┌─────────┬───────┐
│  col1   │ col2  │
│ varchar │ int32 │
├─────────┼───────┤
│ Hannes  │     2 │
│ Mark    │     1 │
└─────────┴───────┘
Binder Error: table "read_parquet" has duplicate column name "COL1"
```


### OS:

ubuntu 22.04 x86_64 

### DuckDB Version:

1.1.3 and bleeding

### DuckDB Client:

cli 

### Hardware:

_No response_

### Full Name:

Nicolas chuche

### Affiliation:

Ministere de la transition écologique

### What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.

I have tested with a nightly build

### Did you include all relevant data sets for reproducing the issue?

Yes

### Did you include all code required to reproduce the issue?

- [X] Yes, I have

### Did you include all relevant configuration (e.g., CPU architecture, Python version, Linux distribution) to reproduce the issue?

- [X] Yes, I have
The Parquet reader considers 'FOO' and 'foo' as duplicate column names when different cases are used for the column name and the partition key.
### What happens?

When a Parquet dataset contains a column names and a partition key which are case-sensitive different but case-insensitive the same, DuckDB fails when reading it.



### To Reproduce

1. Untar this file :
[people.tar.gz](https://github.com/user-attachments/files/18048196/people.tar.gz)

2. use the following SQL

```
.echo on

FROM read_parquet('people/**/*.parquet', hive_partitioning = false);
FROM read_parquet('people/**/*.parquet');
```

3. results : 

```
duckdb-1.1.3 < a.sql

FROM read_parquet('people/**/*.parquet', hive_partitioning = false);
┌─────────┬───────┐
│  col1   │ col2  │
│ varchar │ int32 │
├─────────┼───────┤
│ Hannes  │     2 │
│ Mark    │     1 │
└─────────┴───────┘
Binder Error: table "read_parquet" has duplicate column name "COL1"
```


### OS:

ubuntu 22.04 x86_64 

### DuckDB Version:

1.1.3 and bleeding

### DuckDB Client:

cli 

### Hardware:

_No response_

### Full Name:

Nicolas chuche

### Affiliation:

Ministere de la transition écologique

### What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.

I have tested with a nightly build

### Did you include all relevant data sets for reproducing the issue?

Yes

### Did you include all code required to reproduce the issue?

- [X] Yes, I have

### Did you include all relevant configuration (e.g., CPU architecture, Python version, Linux distribution) to reproduce the issue?

- [X] Yes, I have


Discussion / hints:

Fix patch:
diff --git a/src/common/multi_file_reader.cpp b/src/common/multi_file_reader.cpp
index e81bedcaf114..97eba1014d0d 100644
--- a/src/common/multi_file_reader.cpp
+++ b/src/common/multi_file_reader.cpp
@@ -215,7 +215,9 @@ void MultiFileReader::BindOptions(MultiFileReaderOptions &options, MultiFileList
 
 		for (auto &part : partitions) {
 			idx_t hive_partitioning_index;
-			auto lookup = std::find(names.begin(), names.end(), part.first);
+			auto lookup = std::find_if(names.begin(), names.end(), [&](const string &col_name) {
+				return StringUtil::CIEquals(col_name, part.first);
+			});
 			if (lookup != names.end()) {
 				// hive partitioning column also exists in file - override
 				auto idx = NumericCast<idx_t>(lookup - names.begin());


Test patch:
diff --git a/data/parquet-testing/hive-partitioning/ci-column-names/COL1=Hannes/data_0.parquet b/data/parquet-testing/hive-partitioning/ci-column-names/COL1=Hannes/data_0.parquet
new file mode 100644
index 000000000000..c70efafac6d7
Binary files /dev/null and b/data/parquet-testing/hive-partitioning/ci-column-names/COL1=Hannes/data_0.parquet differ
diff --git a/data/parquet-testing/hive-partitioning/ci-column-names/COL1=Mark/data_0.parquet b/data/parquet-testing/hive-partitioning/ci-column-names/COL1=Mark/data_0.parquet
new file mode 100644
index 000000000000..f7f4c00d7b22
Binary files /dev/null and b/data/parquet-testing/hive-partitioning/ci-column-names/COL1=Mark/data_0.parquet differ
diff --git a/test/sql/copy/partitioned/hive_partition_case_insensitive_column.test b/test/sql/copy/partitioned/hive_partition_case_insensitive_column.test
new file mode 100644
index 000000000000..678e4ec78f6a
--- /dev/null
+++ b/test/sql/copy/partitioned/hive_partition_case_insensitive_column.test
@@ -0,0 +1,11 @@
+# name: test/sql/copy/partitioned/hive_partition_case_insensitive_column.test
+# description: Test when columns in the hive partitioned files differ only in case from the partitions themselves
+# group: [partitioned]
+
+require parquet
+
+query II
+SELECT * FROM  'data/parquet-testing/hive-partitioning/ci-column-names/**/*.parquet' ORDER BY ALL
+----
+Hannes	2
+Mark	1