Repository: duckdb/duckdb (language: python)

Issue:
Segmentation fault
### What happens?

Sometimes a segmentation fault when DuckDB is backed by a file, in-memory it does not issue a seg fault.

Out of 277 datasets, only 5 have this issue. With provided dataset, can always be reproduced.

```
(gdb) bt
#0  0x0000555555775ed6 in std::__shared_ptr<duckdb::DataTableInfo, (__gnu_cxx::_Lock_policy)2>::get (this=0x29c) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:1667
#1  0x00005555557688de in duckdb::shared_ptr<duckdb::DataTableInfo, true>::operator* (this=0x29c) at /home/skinkie/Sources/duckdb/src/include/duckdb/common/shared_ptr_ipp.hpp:196
#2  0x000055555621bb98 in duckdb::RowGroupCollection::GetTableInfo (this=0x28c) at /home/skinkie/Sources/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp:129
#3  0x00005555561e5cc6 in duckdb::RowGroup::GetTableInfo (this=0x55555a7159e0) at /home/skinkie/Sources/duckdb/src/storage/table/row_group.cpp:135
#4  0x00005555561e6c1a in duckdb::RowGroup::AddColumn (this=0x55555a7159e0, new_collection=..., new_column=..., executor=..., result=...) at /home/skinkie/Sources/duckdb/src/storage/table/row_group.cpp:305
#5  0x00005555561f019a in duckdb::RowGroupCollection::AddColumn (this=0x55555a1ee9c0, context=..., new_column=..., default_executor=...) at /home/skinkie/Sources/duckdb/src/storage/table/row_group_collection.cpp:1066
#6  0x0000555556279e05 in duckdb::DataTable::DataTable (this=0x55555a80eaf0, context=..., parent=..., new_column=..., default_value=...) at /home/skinkie/Sources/duckdb/src/storage/data_table.cpp:80
#7  0x00005555557a16e8 in std::_Construct<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (__p=0x55555a80eaf0)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/stl_construct.h:119
#8  0x000055555579c4e8 in std::allocator_traits<std::allocator<void> >::construct<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (__p=0x55555a80eaf0)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/alloc_traits.h:657
#9  std::_Sp_counted_ptr_inplace<duckdb::DataTable, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x55555a80eae0, __a=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:607
#10 0x00005555557974e8 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<duckdb::DataTable, std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x7fffffffa588, __p=@0x7fffffffa580: 0x0, __a=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:969
#11 0x00005555557916e2 in std::__shared_ptr<duckdb::DataTable, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x7fffffffa580, __tag=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:1713
#12 0x0000555555788805 in std::shared_ptr<duckdb::DataTable>::shared_ptr<std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (this=0x7fffffffa580, __tag=...)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr.h:463
#13 0x000055555577cb90 in std::make_shared<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> () at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr.h:1008
#14 0x000055555576f1f0 in duckdb::make_shared_ptr<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> () at /home/skinkie/Sources/duckdb/src/include/duckdb/common/helper.hpp:73
#15 0x0000555555753e98 in duckdb::DuckTableEntry::AddColumn (this=0x55555a196530, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:391
#16 0x000055555575271e in duckdb::DuckTableEntry::AlterEntry (this=0x55555a196530, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:231
#17 0x00005555557522bc in duckdb::DuckTableEntry::AlterEntry (this=0x55555a196530, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:184
#18 0x00005555557b6bd8 in duckdb::CatalogSet::AlterEntry (this=0x55555a16be20, transaction=..., name="kv6_import", alter_info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_set.cpp:328
#19 0x000055555574fcf9 in duckdb::DuckSchemaEntry::Alter (this=0x55555a16bd40, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp:291
#20 0x00005555557b156a in duckdb::Catalog::Alter (this=0x55555a1704e0, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog.cpp:904
#21 0x00005555557b176b in duckdb::Catalog::Alter (this=0x55555a1704e0, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog.cpp:912
#22 0x00005555570b1ff5 in duckdb::PhysicalAlter::GetData (this=0x7fffdc5f55a0, context=..., chunk=..., input=...) at /home/skinkie/Sources/duckdb/src/execution/operator/schema/physical_alter.cpp:13
#23 0x0000555555ff23af in duckdb::PipelineExecutor::GetData (this=0x55555a31e250, chunk=..., input=...) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:478
#24 0x0000555555ff24a0 in duckdb::PipelineExecutor::FetchFromSource (this=0x55555a31e250, result=...) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:504
#25 0x0000555555ff1268 in duckdb::PipelineExecutor::Execute (this=0x55555a31e250, max_chunks=50) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:204
#26 0x0000555555fed597 in duckdb::PipelineTask::ExecuteTask (this=0x7fffdc15fff0, mode=duckdb::TaskExecutionMode::PROCESS_PARTIAL) at /home/skinkie/Sources/duckdb/src/parallel/pipeline.cpp:40
#27 0x0000555555fe7c38 in duckdb::ExecutorTask::Execute (this=0x7fffdc15fff0, mode=duckdb::TaskExecutionMode::PROCESS_PARTIAL) at /home/skinkie/Sources/duckdb/src/parallel/executor_task.cpp:44
#28 0x0000555555feb739 in duckdb::Executor::ExecuteTask (this=0x55555a173350, dry_run=false) at /home/skinkie/Sources/duckdb/src/parallel/executor.cpp:580
#29 0x0000555555eab6d5 in duckdb::ClientContext::ExecuteTaskInternal (this=0x55555a16e960, lock=..., result=..., dry_run=false) at /home/skinkie/Sources/duckdb/src/main/client_context.cpp:557
#30 0x0000555555ec66bd in duckdb::PendingQueryResult::ExecuteTaskInternal (this=0x55555a46b6d0, lock=...) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:68
#31 0x0000555555ec6751 in duckdb::PendingQueryResult::ExecuteInternal (this=0x55555a46b6d0, lock=...) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:75
#32 0x0000555555ec6905 in duckdb::PendingQueryResult::Execute (this=0x55555a46b6d0) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:95
#33 0x0000555555ec72be in duckdb::PreparedStatement::Execute (this=0x55555a4dd5b0, values=..., allow_stream_result=false) at /home/skinkie/Sources/duckdb/src/main/prepared_statement.cpp:85
#34 0x00005555556b91da in duckdb_shell_sqlite3_print_duckbox (pStmt=0x7fffcc091870, max_rows=40, max_width=0, null_value=0x7fffffffc03c "", columnar=0)
    at /home/skinkie/Sources/duckdb/tools/sqlite3_api_wrapper/sqlite3_api_wrapper.cpp:249
#35 0x000055555568be00 in exec_prepared_stmt (pArg=0x7fffffffbf20, pStmt=0x7fffcc091870) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:12752
#36 0x000055555568cc4c in shell_exec (pArg=0x7fffffffbf20, zSql=0x55555a1ef160 "alter table kv6_import add column trip_id varchar(16);", pzErrMsg=0x7fffffffbdb0) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:13087
#37 0x0000555555699c79 in runOneSqlLine (p=0x7fffffffbf20, zSql=0x55555a1ef160 "alter table kv6_import add column trip_id varchar(16);", in=0x55555a31e000, startline=31) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19273
#38 0x000055555569a16f in process_input (p=0x7fffffffbf20) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19384
#39 0x000055555569a49a in process_sqliterc (p=0x7fffffffbf20, sqliterc_override=0x7fffffffd720 "/tmp/script.sql") at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19505
#40 0x000055555569b174 in main (argc=4, argv=0x7fffffffd258) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19951
```

### To Reproduce

```sql
DROP TABLE IF EXISTS kv6_import;
DROP TABLE IF EXISTS tt_import;

CREATE TABLE "kv6_import" (
        "receive"                   TIMESTAMP     NOT NULL,
        "message"                   TIMESTAMP     NOT NULL,
        "vehicle"                   TIMESTAMP     NOT NULL,
        "messagetype"               VARCHAR(10)   NOT NULL,
        "operatingday"              DATE          NOT NULL,
        "dataownercode"             VARCHAR(10)   NOT NULL,
        "lineplanningnumber"        VARCHAR(10),
        "journeynumber"             UINTEGER       NOT NULL,
        "reinforcementnumber"       UTINYINT       NOT NULL,
        "userstopcode"              VARCHAR(10),
        "passagesequencenumber"     TINYINT,
        "distancesincelastuserstop" INTEGER,
        "punctuality"               INTEGER,
        "rd_x"                      VARCHAR(11),
        "rd_y"                      VARCHAR(11),
        "blockcode"                 INTEGER,
        "vehiclenumber"             SMALLINT,
        "wheelchairaccessible"      VARCHAR(5),
        "source"                    VARCHAR(10)   NOT NULL,
        "numberofcoaches"           UTINYINT
);

copy kv6_import from '/tmp/kv6-20240917.log' (DELIMITER ';');

delete from kv6_import where messagetype not in ('ARRIVAL', 'DEPARTURE');

alter table kv6_import add column trip_id varchar(16);

update kv6_import set trip_id = dataownercode || ':' || lineplanningnumber || ':' || journeynumber;

CREATE TABLE "tt_import" (
        "operatingday"          DATE          NOT NULL,
        "trip_id"               VARCHAR(16)   NOT NULL,
        "pointorder"            UTINYINT      NOT NULL,
        "passagesequencenumber" UTINYINT      NOT NULL,
        "userstopcode"          VARCHAR(10)   NOT NULL,
        "targetarrivaltime"     VARCHAR(8)    NOT NULL,
        "targetdeparturetime"   VARCHAR(8)    NOT NULL,
        "recordedarrivaltime"   VARCHAR(8),
        "recordeddeparturetime" VARCHAR(8)
);

copy tt_import from '/tmp/transittimes.csv' (DELIMITER ',');

delete from tt_import where trip_id like 'DOEKSEN:%' or trip_id like 'WSF:%' or trip_id like 'IFF%' or trip_id like 'WPD%' or trip_id like 'TESO%';

alter table tt_import drop column recordedarrivaltime;
alter table tt_import drop column recordeddeparturetime;

update kv6_import set trip_id = w.trip_id from (select tt_import.trip_id as trip_id, z.trip_id as kv6_trip_id, vehiclenumber from tt_import join (select trip_id, userstopcode, vehiclenumber from kv6_import join (select trip_id, min(receive) as receive from kv6_import where trip_id in (select trip_id from kv6_import where trip_id like 'ARR:%' and length(trip_id) = 13  except select trip_id from tt_import) group by trip_id) as y using (trip_id, receive)) as z using (userstopcode) where pointorder = 1 and tt_import.trip_id like z.trip_id[0:8] || '_' || z.trip_id[-5:]) as w where kv6_import.trip_id = kv6_trip_id and kv6_import.vehiclenumber = w.vehiclenumber;

copy (select tt_import.operatingday, tt_import.trip_id, x.reinforcementnumber, x.vehiclenumber, tt_import.userstopcode, tt_import.passagesequencenumber, tt_import.pointorder, tt_import.targetarrivaltime, tt_import.targetdeparturetime, x.arrival as recordedarrivaltime, x.departure as recordeddeparturetime from (select trip_id, reinforcementnumber, vehiclenumber, userstopcode, passagesequencenumber, max(a.receive) as arrival, max(b.receive) as departure from kv6_import as a full outer join kv6_import as b using (trip_id, reinforcementnumber, userstopcode, passagesequencenumber, vehiclenumber) where a.messagetype = 'ARRIVAL' and b.messagetype = 'DEPARTURE' group by trip_id, reinforcementnumber, userstopcode, passagesequencenumber, vehiclenumber) as x right join tt_import using (trip_id, userstopcode, passagesequencenumber) order by trip_id, reinforcementnumber, pointorder) to '/home/skinkie/arriva/volledig-20240917.csv.gz' header;
```

Data:
https://download.stefan.konink.de/duckdb/kv6-20240917.log.gz
https://download.stefan.konink.de/duckdb/transittimes.csv.gz


### OS:

Linux

### DuckDB Version:

main

### DuckDB Client:

cli

### Hardware:

amd64

### Full Name:

Stefan de Konink

### Affiliation:

Stichting OpenGeo

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

I have tested with a source build

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

No - Other reason (please specify in the issue body)

### 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
Segmentation fault
### What happens?

Sometimes a segmentation fault when DuckDB is backed by a file, in-memory it does not issue a seg fault.

Out of 277 datasets, only 5 have this issue. With provided dataset, can always be reproduced.

```
(gdb) bt
#0  0x0000555555775ed6 in std::__shared_ptr<duckdb::DataTableInfo, (__gnu_cxx::_Lock_policy)2>::get (this=0x29c) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:1667
#1  0x00005555557688de in duckdb::shared_ptr<duckdb::DataTableInfo, true>::operator* (this=0x29c) at /home/skinkie/Sources/duckdb/src/include/duckdb/common/shared_ptr_ipp.hpp:196
#2  0x000055555621bb98 in duckdb::RowGroupCollection::GetTableInfo (this=0x28c) at /home/skinkie/Sources/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp:129
#3  0x00005555561e5cc6 in duckdb::RowGroup::GetTableInfo (this=0x55555a7159e0) at /home/skinkie/Sources/duckdb/src/storage/table/row_group.cpp:135
#4  0x00005555561e6c1a in duckdb::RowGroup::AddColumn (this=0x55555a7159e0, new_collection=..., new_column=..., executor=..., result=...) at /home/skinkie/Sources/duckdb/src/storage/table/row_group.cpp:305
#5  0x00005555561f019a in duckdb::RowGroupCollection::AddColumn (this=0x55555a1ee9c0, context=..., new_column=..., default_executor=...) at /home/skinkie/Sources/duckdb/src/storage/table/row_group_collection.cpp:1066
#6  0x0000555556279e05 in duckdb::DataTable::DataTable (this=0x55555a80eaf0, context=..., parent=..., new_column=..., default_value=...) at /home/skinkie/Sources/duckdb/src/storage/data_table.cpp:80
#7  0x00005555557a16e8 in std::_Construct<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (__p=0x55555a80eaf0)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/stl_construct.h:119
#8  0x000055555579c4e8 in std::allocator_traits<std::allocator<void> >::construct<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (__p=0x55555a80eaf0)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/alloc_traits.h:657
#9  std::_Sp_counted_ptr_inplace<duckdb::DataTable, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x55555a80eae0, __a=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:607
#10 0x00005555557974e8 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<duckdb::DataTable, std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x7fffffffa588, __p=@0x7fffffffa580: 0x0, __a=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:969
#11 0x00005555557916e2 in std::__shared_ptr<duckdb::DataTable, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (
    this=0x7fffffffa580, __tag=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr_base.h:1713
#12 0x0000555555788805 in std::shared_ptr<duckdb::DataTable>::shared_ptr<std::allocator<void>, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> (this=0x7fffffffa580, __tag=...)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr.h:463
#13 0x000055555577cb90 in std::make_shared<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> () at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/shared_ptr.h:1008
#14 0x000055555576f1f0 in duckdb::make_shared_ptr<duckdb::DataTable, duckdb::ClientContext&, duckdb::DataTable&, duckdb::ColumnDefinition&, duckdb::Expression&> () at /home/skinkie/Sources/duckdb/src/include/duckdb/common/helper.hpp:73
#15 0x0000555555753e98 in duckdb::DuckTableEntry::AddColumn (this=0x55555a196530, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:391
#16 0x000055555575271e in duckdb::DuckTableEntry::AlterEntry (this=0x55555a196530, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:231
#17 0x00005555557522bc in duckdb::DuckTableEntry::AlterEntry (this=0x55555a196530, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp:184
#18 0x00005555557b6bd8 in duckdb::CatalogSet::AlterEntry (this=0x55555a16be20, transaction=..., name="kv6_import", alter_info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_set.cpp:328
#19 0x000055555574fcf9 in duckdb::DuckSchemaEntry::Alter (this=0x55555a16bd40, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp:291
#20 0x00005555557b156a in duckdb::Catalog::Alter (this=0x55555a1704e0, transaction=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog.cpp:904
#21 0x00005555557b176b in duckdb::Catalog::Alter (this=0x55555a1704e0, context=..., info=...) at /home/skinkie/Sources/duckdb/src/catalog/catalog.cpp:912
#22 0x00005555570b1ff5 in duckdb::PhysicalAlter::GetData (this=0x7fffdc5f55a0, context=..., chunk=..., input=...) at /home/skinkie/Sources/duckdb/src/execution/operator/schema/physical_alter.cpp:13
#23 0x0000555555ff23af in duckdb::PipelineExecutor::GetData (this=0x55555a31e250, chunk=..., input=...) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:478
#24 0x0000555555ff24a0 in duckdb::PipelineExecutor::FetchFromSource (this=0x55555a31e250, result=...) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:504
#25 0x0000555555ff1268 in duckdb::PipelineExecutor::Execute (this=0x55555a31e250, max_chunks=50) at /home/skinkie/Sources/duckdb/src/parallel/pipeline_executor.cpp:204
#26 0x0000555555fed597 in duckdb::PipelineTask::ExecuteTask (this=0x7fffdc15fff0, mode=duckdb::TaskExecutionMode::PROCESS_PARTIAL) at /home/skinkie/Sources/duckdb/src/parallel/pipeline.cpp:40
#27 0x0000555555fe7c38 in duckdb::ExecutorTask::Execute (this=0x7fffdc15fff0, mode=duckdb::TaskExecutionMode::PROCESS_PARTIAL) at /home/skinkie/Sources/duckdb/src/parallel/executor_task.cpp:44
#28 0x0000555555feb739 in duckdb::Executor::ExecuteTask (this=0x55555a173350, dry_run=false) at /home/skinkie/Sources/duckdb/src/parallel/executor.cpp:580
#29 0x0000555555eab6d5 in duckdb::ClientContext::ExecuteTaskInternal (this=0x55555a16e960, lock=..., result=..., dry_run=false) at /home/skinkie/Sources/duckdb/src/main/client_context.cpp:557
#30 0x0000555555ec66bd in duckdb::PendingQueryResult::ExecuteTaskInternal (this=0x55555a46b6d0, lock=...) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:68
#31 0x0000555555ec6751 in duckdb::PendingQueryResult::ExecuteInternal (this=0x55555a46b6d0, lock=...) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:75
#32 0x0000555555ec6905 in duckdb::PendingQueryResult::Execute (this=0x55555a46b6d0) at /home/skinkie/Sources/duckdb/src/main/pending_query_result.cpp:95
#33 0x0000555555ec72be in duckdb::PreparedStatement::Execute (this=0x55555a4dd5b0, values=..., allow_stream_result=false) at /home/skinkie/Sources/duckdb/src/main/prepared_statement.cpp:85
#34 0x00005555556b91da in duckdb_shell_sqlite3_print_duckbox (pStmt=0x7fffcc091870, max_rows=40, max_width=0, null_value=0x7fffffffc03c "", columnar=0)
    at /home/skinkie/Sources/duckdb/tools/sqlite3_api_wrapper/sqlite3_api_wrapper.cpp:249
#35 0x000055555568be00 in exec_prepared_stmt (pArg=0x7fffffffbf20, pStmt=0x7fffcc091870) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:12752
#36 0x000055555568cc4c in shell_exec (pArg=0x7fffffffbf20, zSql=0x55555a1ef160 "alter table kv6_import add column trip_id varchar(16);", pzErrMsg=0x7fffffffbdb0) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:13087
#37 0x0000555555699c79 in runOneSqlLine (p=0x7fffffffbf20, zSql=0x55555a1ef160 "alter table kv6_import add column trip_id varchar(16);", in=0x55555a31e000, startline=31) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19273
#38 0x000055555569a16f in process_input (p=0x7fffffffbf20) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19384
#39 0x000055555569a49a in process_sqliterc (p=0x7fffffffbf20, sqliterc_override=0x7fffffffd720 "/tmp/script.sql") at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19505
#40 0x000055555569b174 in main (argc=4, argv=0x7fffffffd258) at /home/skinkie/Sources/duckdb/tools/shell/shell.c:19951
```

### To Reproduce

```sql
DROP TABLE IF EXISTS kv6_import;
DROP TABLE IF EXISTS tt_import;

CREATE TABLE "kv6_import" (
        "receive"                   TIMESTAMP     NOT NULL,
        "message"                   TIMESTAMP     NOT NULL,
        "vehicle"                   TIMESTAMP     NOT NULL,
        "messagetype"               VARCHAR(10)   NOT NULL,
        "operatingday"              DATE          NOT NULL,
        "dataownercode"             VARCHAR(10)   NOT NULL,
        "lineplanningnumber"        VARCHAR(10),
        "journeynumber"             UINTEGER       NOT NULL,
        "reinforcementnumber"       UTINYINT       NOT NULL,
        "userstopcode"              VARCHAR(10),
        "passagesequencenumber"     TINYINT,
        "distancesincelastuserstop" INTEGER,
        "punctuality"               INTEGER,
        "rd_x"                      VARCHAR(11),
        "rd_y"                      VARCHAR(11),
        "blockcode"                 INTEGER,
        "vehiclenumber"             SMALLINT,
        "wheelchairaccessible"      VARCHAR(5),
        "source"                    VARCHAR(10)   NOT NULL,
        "numberofcoaches"           UTINYINT
);

copy kv6_import from '/tmp/kv6-20240917.log' (DELIMITER ';');

delete from kv6_import where messagetype not in ('ARRIVAL', 'DEPARTURE');

alter table kv6_import add column trip_id varchar(16);

update kv6_import set trip_id = dataownercode || ':' || lineplanningnumber || ':' || journeynumber;

CREATE TABLE "tt_import" (
        "operatingday"          DATE          NOT NULL,
        "trip_id"               VARCHAR(16)   NOT NULL,
        "pointorder"            UTINYINT      NOT NULL,
        "passagesequencenumber" UTINYINT      NOT NULL,
        "userstopcode"          VARCHAR(10)   NOT NULL,
        "targetarrivaltime"     VARCHAR(8)    NOT NULL,
        "targetdeparturetime"   VARCHAR(8)    NOT NULL,
        "recordedarrivaltime"   VARCHAR(8),
        "recordeddeparturetime" VARCHAR(8)
);

copy tt_import from '/tmp/transittimes.csv' (DELIMITER ',');

delete from tt_import where trip_id like 'DOEKSEN:%' or trip_id like 'WSF:%' or trip_id like 'IFF%' or trip_id like 'WPD%' or trip_id like 'TESO%';

alter table tt_import drop column recordedarrivaltime;
alter table tt_import drop column recordeddeparturetime;

update kv6_import set trip_id = w.trip_id from (select tt_import.trip_id as trip_id, z.trip_id as kv6_trip_id, vehiclenumber from tt_import join (select trip_id, userstopcode, vehiclenumber from kv6_import join (select trip_id, min(receive) as receive from kv6_import where trip_id in (select trip_id from kv6_import where trip_id like 'ARR:%' and length(trip_id) = 13  except select trip_id from tt_import) group by trip_id) as y using (trip_id, receive)) as z using (userstopcode) where pointorder = 1 and tt_import.trip_id like z.trip_id[0:8] || '_' || z.trip_id[-5:]) as w where kv6_import.trip_id = kv6_trip_id and kv6_import.vehiclenumber = w.vehiclenumber;

copy (select tt_import.operatingday, tt_import.trip_id, x.reinforcementnumber, x.vehiclenumber, tt_import.userstopcode, tt_import.passagesequencenumber, tt_import.pointorder, tt_import.targetarrivaltime, tt_import.targetdeparturetime, x.arrival as recordedarrivaltime, x.departure as recordeddeparturetime from (select trip_id, reinforcementnumber, vehiclenumber, userstopcode, passagesequencenumber, max(a.receive) as arrival, max(b.receive) as departure from kv6_import as a full outer join kv6_import as b using (trip_id, reinforcementnumber, userstopcode, passagesequencenumber, vehiclenumber) where a.messagetype = 'ARRIVAL' and b.messagetype = 'DEPARTURE' group by trip_id, reinforcementnumber, userstopcode, passagesequencenumber, vehiclenumber) as x right join tt_import using (trip_id, userstopcode, passagesequencenumber) order by trip_id, reinforcementnumber, pointorder) to '/home/skinkie/arriva/volledig-20240917.csv.gz' header;
```

Data:
https://download.stefan.konink.de/duckdb/kv6-20240917.log.gz
https://download.stefan.konink.de/duckdb/transittimes.csv.gz


### OS:

Linux

### DuckDB Version:

main

### DuckDB Client:

cli

### Hardware:

amd64

### Full Name:

Stefan de Konink

### Affiliation:

Stichting OpenGeo

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

I have tested with a source build

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

No - Other reason (please specify in the issue body)

### 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/.github/regression/realnest.csv b/.github/regression/realnest.csv
new file mode 100644
index 000000000000..e63a1d144dc9
--- /dev/null
+++ b/.github/regression/realnest.csv
@@ -0,0 +1,16 @@
+benchmark/realnest/01_aggregate-first-level-struct-members.benchmark
+benchmark/realnest/02_list_sort.benchmark
+benchmark/realnest/03_create_table_from_unnested_structs.benchmark
+benchmark/realnest/04_list_transform_and_list_aggregate.benchmark
+benchmark/realnest/05_list_filter.benchmark
+benchmark/realnest/06_list_filter_on_unnested_structure.benchmark
+benchmark/realnest/07_list_unique_on_transformed_and_aggregated_list.benchmark
+benchmark/realnest/08_count_map_keys.benchmark
+benchmark/realnest/09_array_agg.benchmark
+benchmark/realnest/11_list_sort_reduce_transform.benchmark
+benchmark/realnest/12_map_list_values.benchmark
+benchmark/realnest/13_multi_join_nested_data_with_filtering.benchmark
+benchmark/realnest/14_list_slice.benchmark
+benchmark/realnest/15_list_sort.benchmark
+benchmark/realnest/16_most_common_list_aggregates.benchmark
+benchmark/realnest/17_list_aggregates_histogram_stddev_mode.benchmark
\ No newline at end of file
diff --git a/.github/workflows/Regression.yml b/.github/workflows/Regression.yml
index 25b5a470f77a..b1cf112b10a2 100644
--- a/.github/workflows/Regression.yml
+++ b/.github/workflows/Regression.yml
@@ -35,300 +35,311 @@ env:
   BASE_BRANCH: ${{ github.base_ref || (endsWith(github.ref, '_feature') && 'feature' || 'main') }}
 
 jobs:
- regression-test-benchmark-runner:
-  name: Regression Tests
-  runs-on: ubuntu-20.04
-  env:
-    CC: gcc-10
-    CXX: g++-10
-    GEN: ninja
-    BUILD_BENCHMARK: 1
-    BUILD_TPCH: 1
-    BUILD_TPCDS: 1
-    BUILD_HTTPFS: 1
-    BUILD_JEMALLOC: 1
-    CORE_EXTENSIONS: "inet"
-
-  steps:
-    - uses: actions/checkout@v4
-      with:
-        fetch-depth: 0
-
-    - uses: actions/setup-python@v5
-      with:
-        python-version: '3.12'
-
-    - name: Install
-      shell: bash
-      run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build && pip install requests
-
-    - name: Setup Ccache
-      uses: hendrikmuhs/ccache-action@main
-      with:
-        key: ${{ github.job }}
-        save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }}
-
-    - name: Build
-      shell: bash
-      run: |
-        make
-        git clone --branch ${{ env.BASE_BRANCH }} https://github.com/duckdb/duckdb.git --depth=1
-        cd duckdb
-        make
-        cd ..
-
-    - name: Set up benchmarks
-      shell: bash
-      run: |
-        cp -r benchmark duckdb/
-
-    - name: Regression Test Micro
-      if: always()
-      shell: bash
-      run: |
-        python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/micro.csv --verbose --threads=2
-
-    - name: Regression Test Ingestion Perf
-      if: always()
-      shell: bash
-      run: |
-        python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/ingestion.csv --verbose --threads=2
-
-    - name: Regression Test TPCH
-      if: always()
-      shell: bash
-      run: |
-        python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/tpch.csv --verbose --threads=2
-
-    - name: Regression Test TPCH-PARQUET
-      if: always()
-      shell: bash
-      run: |
-        python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/tpch_parquet.csv --verbose --threads=2
-
-    - name: Regression Test TPCDS
-      if: always()
-      shell: bash
-      run: |
-        python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/tpcds.csv --verbose --threads=2
-
-    - name: Regression Test H2OAI
-      if: always()
-      shell: bash
-      run: |
-        python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/h2oai.csv --verbose --threads=2
-
-    - name: Regression Test IMDB
-      if: always()
-      shell: bash
-      run: |
-        python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/imdb.csv --verbose --threads=2
-
-    - name: Regression Test CSV
-      if: always()
-      shell: bash
-      run: |
-        python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/csv.csv --verbose --threads=2
-
- regression-test-storage:
-  name: Storage Size Regression Test
-  runs-on: ubuntu-20.04
-  env:
-    CC: gcc-10
-    CXX: g++-10
-    GEN: ninja
-    BUILD_TPCH: 1
-    BUILD_TPCDS: 1
-
-  steps:
-    - uses: actions/checkout@v4
-      with:
-        fetch-depth: 0
-
-    - uses: actions/setup-python@v5
-      with:
-        python-version: '3.12'
-
-    - name: Install
-      shell: bash
-      run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build && pip install requests
-
-    - name: Setup Ccache
-      uses: hendrikmuhs/ccache-action@main
-      with:
-        key: ${{ github.job }}
-        save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }}
-
-    - name: Build
-      shell: bash
-      run: |
-        make
-        git clone --branch ${{ env.BASE_BRANCH }} https://github.com/duckdb/duckdb.git --depth=1
-        cd duckdb
-        make
-        cd ..
-
-    - name: Regression Test
-      shell: bash
-      run: |
-        python scripts/regression_test_storage_size.py --old=duckdb/build/release/duckdb --new=build/release/duckdb
-
-    - name: Test for incompatibility
-      shell: bash
-      run: |
-        if (cmp test/sql/storage_version/storage_version.db duckdb/test/sql/storage_version/storage_version.db); then
-          echo "storage_changed=false" >> $GITHUB_ENV
-        else
-          echo "storage_changed=true" >> $GITHUB_ENV
-        fi
-
-    - name: Regression Compatibility Test (testing bidirectional compatibility)
-      shell: bash
-      if: env.storage_changed == 'false'
-      run: |
-        # Regenerate test/sql/storage_version.db with newer version -> read with older version
-        python3 scripts/generate_storage_version.py
-        ./duckdb/build/release/duckdb test/sql/storage_version/storage_version.db
-        # Regenerate test/sql/storage_version.db with older version -> read with newer version (already performed as part of test.slow)
-        cd duckdb
-        python3 ../scripts/generate_storage_version.py
-        ../build/release/duckdb duckdb/test/sql/storage_version/storage_version.db
-        cd ..
-
-    - name: Regression Compatibility Test (testing storage version has been bumped)
-      shell: bash
-      if: env.storage_changed == 'true'
-      run: |
-        python3 scripts/generate_storage_version.py
-        cd duckdb
-        python3 scripts/generate_storage_version.py
-        cd ..
-        if (cmp -i 8 -n 12 test/sql/storage_version.db duckdb/test/sql/storage_version.db); then
-           echo "Expected storage format to be bumped, but this is not the case"
-           echo "This might fail spuriously if changes to content of test database / generation script happened"
-           exit 1
-        else
-           echo "Storage bump detected, all good!"
-        fi
-
- regression-test-python:
-  name: Regression Test (Python Client)
-  runs-on: ubuntu-20.04
-  env:
-    CC: gcc-10
-    CXX: g++-10
-    GEN: ninja
-
-  steps:
-    - uses: actions/checkout@v4
-      with:
-        fetch-depth: 0
-
-    - uses: actions/setup-python@v5
-      with:
-        python-version: '3.12'
-
-    - name: Install
-      shell: bash
-      run: |
-        sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build
-        pip install numpy pytest pandas mypy psutil pyarrow
-
-    - name: Setup Ccache
-      uses: hendrikmuhs/ccache-action@main
-      with:
-        key: ${{ github.job }}
-        save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }}
-
-    - name: Build Current Version
-      shell: bash
-      run: |
-        cd tools/pythonpkg
-        pip install --use-pep517 . --user
-        cd ../..
-
-    - name: Run New Version
-      shell: bash
-      run: |
-        python scripts/regression_test_python.py --threads=2 --out-file=new.csv
-
-    - name: Cleanup New Version
-      shell: bash
-      run: |
-        cd tools/pythonpkg
-        ./clean.sh
-        cd ../..
-
-    - name: Build Current
-      shell: bash
-      run: |
-        git clone --branch ${{ env.BASE_BRANCH }} https://github.com/duckdb/duckdb.git --depth=1
-        cd duckdb/tools/pythonpkg
-        pip install --use-pep517 . --user
-        cd ../../..
-
-    - name: Run Current Version
-      shell: bash
-      run: |
-        python scripts/regression_test_python.py --threads=2 --out-file=current.csv
-
-    - name: Regression Test
-      shell: bash
-      run: |
-        cp -r benchmark duckdb/
-        python scripts/regression_check.py --old=current.csv --new=new.csv
-
- regression-test-plan-cost:
-  name: Regression Test Join Order Plan Cost
-  runs-on: ubuntu-20.04
-  env:
-    CC: gcc-10
-    CXX: g++-10
-    GEN: ninja
-    BUILD_TPCH: 1
-    BUILD_HTTPFS: 1
-
-  steps:
-    - uses: actions/checkout@v4
-      with:
-        fetch-depth: 0
-
-    - uses: actions/setup-python@v5
-      with:
-        python-version: '3.12'
-
-    - name: Install
-      shell: bash
-      run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build && pip install tqdm
-
-    - name: Setup Ccache
-      uses: hendrikmuhs/ccache-action@main
-      with:
-        key: ${{ github.job }}
-        save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }}
-
-    - name: Build
-      shell: bash
-      run: |
-        make
-        git clone --branch ${{ env.BASE_BRANCH }} https://github.com/duckdb/duckdb.git --depth=1
-        cd duckdb
-        make
-        cd ..
-
-    - name: Set up benchmarks
-      shell: bash
-      run: |
-        cp -r benchmark duckdb/
-
-    - name: Regression Test IMDB
-      if: always()
-      shell: bash
-      run: |
-        python scripts/plan_cost_runner.py --old=duckdb/build/release/duckdb --new=build/release/duckdb --dir=benchmark/imdb_plan_cost
-
-    - name: Regression Test TPCH
-      if: always()
-      shell: bash
-      run: |
-        python scripts/plan_cost_runner.py --old=duckdb/build/release/duckdb --new=build/release/duckdb --dir=benchmark/tpch_plan_cost
+  regression-test-benchmark-runner:
+    name: Regression Tests
+    runs-on: ubuntu-20.04
+    env:
+      CC: gcc-10
+      CXX: g++-10
+      GEN: ninja
+      BUILD_BENCHMARK: 1
+      BUILD_TPCH: 1
+      BUILD_TPCDS: 1
+      BUILD_HTTPFS: 1
+      BUILD_JEMALLOC: 1
+      BUILD_JSON: 1
+      CORE_EXTENSIONS: "inet"
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - uses: actions/setup-python@v5
+        with:
+          python-version: '3.12'
+
+      - name: Install
+        shell: bash
+        run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build && pip install requests
+
+      - name: Setup Ccache
+        uses: hendrikmuhs/ccache-action@main
+        with:
+          key: ${{ github.job }}
+          save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }}
+
+      - name: Build
+        shell: bash
+        run: |
+          make
+          git clone --branch ${{ env.BASE_BRANCH }} https://github.com/duckdb/duckdb.git --depth=1
+          cd duckdb
+          make
+          cd ..
+
+      - name: Set up benchmarks
+        shell: bash
+        run: |
+          cp -r benchmark duckdb/
+
+      - name: Regression Test Micro
+        if: always()
+        shell: bash
+        run: |
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/micro.csv --verbose --threads=2
+
+      - name: Regression Test Ingestion Perf
+        if: always()
+        shell: bash
+        run: |
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/ingestion.csv --verbose --threads=2
+
+      - name: Regression Test TPCH
+        if: always()
+        shell: bash
+        run: |
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/tpch.csv --verbose --threads=2
+
+      - name: Regression Test TPCH-PARQUET
+        if: always()
+        shell: bash
+        run: |
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/tpch_parquet.csv --verbose --threads=2
+
+      - name: Regression Test TPCDS
+        if: always()
+        shell: bash
+        run: |
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/tpcds.csv --verbose --threads=2
+
+      - name: Regression Test H2OAI
+        if: always()
+        shell: bash
+        run: |
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/h2oai.csv --verbose --threads=2
+
+      - name: Regression Test IMDB
+        if: always()
+        shell: bash
+        run: |
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/imdb.csv --verbose --threads=2
+
+      - name: Regression Test CSV
+        if: always()
+        shell: bash
+        run: |
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/csv.csv --verbose --threads=2
+
+      - name: Regression Test RealNest 
+        if: always()
+        shell: bash
+        run: |
+          mkdir -p duckdb_benchmark_data
+          mkdir -p duckdb/duckdb_benchmark_data
+          wget https://duckdb-blobs.s3.amazonaws.com/data/realnest/realnest.duckdb --output-document=duckdb_benchmark_data/real_nest.duckdb
+          cp duckdb_benchmark_data/real_nest.duckdb duckdb/duckdb_benchmark_data/real_nest.duckdb
+          python scripts/regression_test_runner.py --old=duckdb/build/release/benchmark/benchmark_runner --new=build/release/benchmark/benchmark_runner --benchmarks=.github/regression/realnest.csv --verbose --threads=2
+         
+  regression-test-storage:
+    name: Storage Size Regression Test
+    runs-on: ubuntu-20.04
+    env:
+      CC: gcc-10
+      CXX: g++-10
+      GEN: ninja
+      BUILD_TPCH: 1
+      BUILD_TPCDS: 1
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - uses: actions/setup-python@v5
+        with:
+          python-version: '3.12'
+
+      - name: Install
+        shell: bash
+        run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build && pip install requests
+
+      - name: Setup Ccache
+        uses: hendrikmuhs/ccache-action@main
+        with:
+          key: ${{ github.job }}
+          save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }}
+
+      - name: Build
+        shell: bash
+        run: |
+          make
+          git clone --branch ${{ env.BASE_BRANCH }} https://github.com/duckdb/duckdb.git --depth=1
+          cd duckdb
+          make
+          cd ..
+
+      - name: Regression Test
+        shell: bash
+        run: |
+          python scripts/regression_test_storage_size.py --old=duckdb/build/release/duckdb --new=build/release/duckdb
+
+      - name: Test for incompatibility
+        shell: bash
+        run: |
+          if (cmp test/sql/storage_version/storage_version.db duckdb/test/sql/storage_version/storage_version.db); then
+            echo "storage_changed=false" >> $GITHUB_ENV
+          else
+            echo "storage_changed=true" >> $GITHUB_ENV
+          fi
+
+      - name: Regression Compatibility Test (testing bidirectional compatibility)
+        shell: bash
+        if: env.storage_changed == 'false'
+        run: |
+          # Regenerate test/sql/storage_version.db with newer version -> read with older version
+          python3 scripts/generate_storage_version.py
+          ./duckdb/build/release/duckdb test/sql/storage_version/storage_version.db
+          # Regenerate test/sql/storage_version.db with older version -> read with newer version (already performed as part of test.slow)
+          cd duckdb
+          python3 ../scripts/generate_storage_version.py
+          ../build/release/duckdb duckdb/test/sql/storage_version/storage_version.db
+          cd ..
+
+      - name: Regression Compatibility Test (testing storage version has been bumped)
+        shell: bash
+        if: env.storage_changed == 'true'
+        run: |
+          python3 scripts/generate_storage_version.py
+          cd duckdb
+          python3 scripts/generate_storage_version.py
+          cd ..
+          if (cmp -i 8 -n 12 test/sql/storage_version.db duckdb/test/sql/storage_version.db); then
+            echo "Expected storage format to be bumped, but this is not the case"
+            echo "This might fail spuriously if changes to content of test database / generation script happened"
+            exit 1
+          else
+            echo "Storage bump detected, all good!"
+          fi
+
+  regression-test-python:
+    name: Regression Test (Python Client)
+    runs-on: ubuntu-20.04
+    env:
+      CC: gcc-10
+      CXX: g++-10
+      GEN: ninja
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - uses: actions/setup-python@v5
+        with:
+          python-version: '3.12'
+
+      - name: Install
+        shell: bash
+        run: |
+          sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build
+          pip install numpy pytest pandas mypy psutil pyarrow
+
+      - name: Setup Ccache
+        uses: hendrikmuhs/ccache-action@main
+        with:
+          key: ${{ github.job }}
+          save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }}
+
+      - name: Build Current Version
+        shell: bash
+        run: |
+          cd tools/pythonpkg
+          pip install --use-pep517 . --user
+          cd ../..
+
+      - name: Run New Version
+        shell: bash
+        run: |
+          python scripts/regression_test_python.py --threads=2 --out-file=new.csv
+
+      - name: Cleanup New Version
+        shell: bash
+        run: |
+          cd tools/pythonpkg
+          ./clean.sh
+          cd ../..
+
+      - name: Build Current
+        shell: bash
+        run: |
+          git clone --branch ${{ env.BASE_BRANCH }} https://github.com/duckdb/duckdb.git --depth=1
+          cd duckdb/tools/pythonpkg
+          pip install --use-pep517 . --user
+          cd ../../..
+
+      - name: Run Current Version
+        shell: bash
+        run: |
+          python scripts/regression_test_python.py --threads=2 --out-file=current.csv
+
+      - name: Regression Test
+        shell: bash
+        run: |
+          cp -r benchmark duckdb/
+          python scripts/regression_check.py --old=current.csv --new=new.csv
+
+  regression-test-plan-cost:
+    name: Regression Test Join Order Plan Cost
+    runs-on: ubuntu-20.04
+    env:
+      CC: gcc-10
+      CXX: g++-10
+      GEN: ninja
+      BUILD_TPCH: 1
+      BUILD_HTTPFS: 1
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - uses: actions/setup-python@v5
+        with:
+          python-version: '3.12'
+
+      - name: Install
+        shell: bash
+        run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build && pip install tqdm
+
+      - name: Setup Ccache
+        uses: hendrikmuhs/ccache-action@main
+        with:
+          key: ${{ github.job }}
+          save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }}
+
+      - name: Build
+        shell: bash
+        run: |
+          make
+          git clone --branch ${{ env.BASE_BRANCH }} https://github.com/duckdb/duckdb.git --depth=1
+          cd duckdb
+          make
+          cd ..
+
+      - name: Set up benchmarks
+        shell: bash
+        run: |
+          cp -r benchmark duckdb/
+
+      - name: Regression Test IMDB
+        if: always()
+        shell: bash
+        run: |
+          python scripts/plan_cost_runner.py --old=duckdb/build/release/duckdb --new=build/release/duckdb --dir=benchmark/imdb_plan_cost
+
+      - name: Regression Test TPCH
+        if: always()
+        shell: bash
+        run: |
+          python scripts/plan_cost_runner.py --old=duckdb/build/release/duckdb --new=build/release/duckdb --dir=benchmark/tpch_plan_cost
diff --git a/benchmark/realnest/01_aggregate-first-level-struct-members.benchmark b/benchmark/realnest/01_aggregate-first-level-struct-members.benchmark
new file mode 100644
index 000000000000..4bb47a74a7fa
--- /dev/null
+++ b/benchmark/realnest/01_aggregate-first-level-struct-members.benchmark
@@ -0,0 +1,27 @@
+# name: benchmark/realnest/01_aggregate-first-level-struct-members.benchmark
+# description: Aggregate functions on the struct, group by one parameter
+# group: [realnest]
+
+name aggregate-first-level-struct-members
+
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT PV.npvs,
+      sum(PV.x) AS sum_x,
+      sum(PV.y) AS sum_y,
+      sum(PV.z) AS sum_z,
+      avg(MET.pt) AS avg_pt,
+      min(MET.phi) AS min_phi,
+      max(MET.sumet) AS max_sumet
+FROM run2012B_singleMu
+GROUP BY PV.npvs
+HAVING sum_x > 1;
\ No newline at end of file
diff --git a/benchmark/realnest/02_list_sort.benchmark b/benchmark/realnest/02_list_sort.benchmark
new file mode 100644
index 000000000000..b97351fa5096
--- /dev/null
+++ b/benchmark/realnest/02_list_sort.benchmark
@@ -0,0 +1,17 @@
+# name: benchmark/realnest/02_list_sort.benchmark
+# description: list_sort text entries
+# group: [realnest]
+
+name list_sort
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT list_sort(body_text) FROM cord;
\ No newline at end of file
diff --git a/benchmark/realnest/03_create_table_from_unnested_structs.benchmark b/benchmark/realnest/03_create_table_from_unnested_structs.benchmark
new file mode 100644
index 000000000000..7bc78d59b7de
--- /dev/null
+++ b/benchmark/realnest/03_create_table_from_unnested_structs.benchmark
@@ -0,0 +1,43 @@
+# name: benchmark/realnest/03_create_table_from_unnested_structs.benchmark
+# description: Create a table by unnesting and joining the structs in a JSON file
+# group: [realnest]
+
+name create_table_from_unnested_structs
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+CREATE OR REPLACE TABLE combined AS 
+(SELECT unnested_hlt.*,
+    unnested_pv.*,
+    unnested_met.*,
+    unnested_muon.*,
+    unnested_electron.*,
+    unnested_tau.*,
+    unnested_photon.*,
+    unnested_jet.*
+FROM 
+    (SELECT rowid, UNNEST(HLT) AS hlt FROM run2012B_singleMu) AS unnested_hlt
+    LEFT JOIN
+    (SELECT rowid, UNNEST(PV) AS pv FROM run2012B_singleMu) AS unnested_pv ON unnested_hlt.rowid = unnested_pv.rowid
+    LEFT JOIN
+    (SELECT rowid, UNNEST(MET) AS met FROM run2012B_singleMu) AS unnested_met ON unnested_hlt.rowid = unnested_met.rowid
+    LEFT JOIN
+    (SELECT rowid, UNNEST(Muon, recursive:=true) AS muon FROM run2012B_singleMu) AS unnested_muon ON unnested_hlt.rowid = unnested_muon.rowid
+    LEFT JOIN
+    (SELECT rowid, UNNEST(Electron, recursive:=true) AS electron FROM run2012B_singleMu) AS unnested_electron ON unnested_hlt.rowid = unnested_electron.rowid
+    LEFT JOIN
+    (SELECT rowid, UNNEST(Tau, recursive:=true) AS tau FROM run2012B_singleMu) AS unnested_tau ON unnested_hlt.rowid = unnested_tau.rowid
+    LEFT JOIN
+    (SELECT rowid, UNNEST(Photon, recursive:=true) AS photon FROM run2012B_singleMu) AS unnested_photon ON unnested_hlt.rowid = unnested_photon.rowid
+    LEFT JOIN
+    (SELECT rowid, UNNEST(Jet, recursive:=true) AS jet FROM run2012B_singleMu) AS unnested_jet ON unnested_hlt.rowid = unnested_jet.rowid
+LIMIT 100000
+);
\ No newline at end of file
diff --git a/benchmark/realnest/04_list_transform_and_list_aggregate.benchmark b/benchmark/realnest/04_list_transform_and_list_aggregate.benchmark
new file mode 100644
index 000000000000..8d9904bd4883
--- /dev/null
+++ b/benchmark/realnest/04_list_transform_and_list_aggregate.benchmark
@@ -0,0 +1,61 @@
+# name: benchmark/realnest/04_list_transform_and_list_aggregate.benchmark
+# description: select average from transformed list and group by, having
+# group: [realnest]
+
+name list_transform plus list_aggregate
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT
+  list_aggregate(list_transform(Jet, x -> x.pt), 'avg') AS avg_pt,
+  list_aggregate(list_transform(Jet, x -> x.eta), 'avg') AS avg_eta,
+  list_aggregate(list_transform(Jet, x -> x.phi), 'avg') AS avg_phi,
+  list_aggregate(list_transform(Jet, x -> x.mass), 'avg') AS avg_mass,
+  list_aggregate(list_transform(Jet, x -> x.btag), 'avg') AS avg_btag,
+  list_aggregate(list_transform(Photon, x -> x.pt), 'avg') AS ph_avg_pt,
+  list_aggregate(list_transform(Photon, x -> x.eta), 'avg') AS ph_avg_eta,
+  list_aggregate(list_transform(Photon, x -> x.phi), 'avg') AS ph_avg_phi,
+  list_aggregate(list_transform(Photon, x -> x.mass), 'avg') AS ph_avg_mass,
+  list_aggregate(list_transform(Photon, x -> x.pfreliso03_all), 'avg') AS ph_avg_pf,
+  list_aggregate(list_transform(Photon, x -> x.jetidx), 'avg') AS ph_avg_jet,
+  list_aggregate(list_transform(Photon, x -> x.genpartidx), 'avg') AS ph_avg_gen,
+  list_aggregate(list_transform(Tau, x -> x.pt), 'avg') AS t_avg_pt,
+  list_aggregate(list_transform(Tau, x -> x.eta), 'avg') AS t_avg_eta,
+  list_aggregate(list_transform(Tau, x -> x.mass), 'avg') AS t_avg_mass,
+  list_aggregate(list_transform(Tau, x -> x.decaymode), 'avg') AS t_avg_dec,
+  list_aggregate(list_transform(Tau, x -> x.reliso_all), 'avg') AS t_avg_rel,
+  list_aggregate(list_transform(Tau, x -> x.jetidx), 'avg') AS t_avg_jet,
+  list_aggregate(list_transform(Tau, x -> x.genpartidx), 'avg') AS t_avg_gen,
+  list_aggregate(list_transform(Electron, x -> x.pt), 'avg') AS el_avg_pt,
+  list_aggregate(list_transform(Electron, x -> x.eta), 'avg') AS el_avg_eta,
+  list_aggregate(list_transform(Electron, x -> x.phi), 'avg') AS el_avg_phi,
+  list_aggregate(list_transform(Electron, x -> x.mass), 'avg') AS el_avg_mass,
+  list_aggregate(list_transform(Electron, x -> x.pfreliso03_all), 'avg') AS el_avg_pf,
+  list_aggregate(list_transform(Electron, x -> x.dxy), 'avg') AS el_avg_dxy,
+  list_aggregate(list_transform(Electron, x -> x.dxyerr), 'avg') AS el_avg_dxyer,
+  list_aggregate(list_transform(Electron, x -> x.dz), 'avg') AS el_avg_dz,
+  list_aggregate(list_transform(Electron, x -> x.dzerr), 'avg') AS el_avg_dzer,
+  list_aggregate(list_transform(Electron, x -> x.jetidx), 'avg') AS el_avg_jet,
+  list_aggregate(list_transform(Electron, x -> x.genpartidx), 'avg') AS el_avg_gen, 
+  list_aggregate(list_transform(Muon, x -> x.pt), 'avg') AS mu_avg_pt, 
+  list_aggregate(list_transform(Muon, x -> x.eta), 'avg') AS mu_avg_eta, 
+  list_aggregate(list_transform(Muon, x -> x.phi), 'avg') AS mu_avg_phi, 
+  list_aggregate(list_transform(Muon, x -> x.mass), 'avg') AS mu_avg_mas, 
+  list_aggregate(list_transform(Muon, x -> x.pfreliso03_all), 'avg') AS mu_avg_pf3, 
+  list_aggregate(list_transform(Muon, x -> x.pfreliso04_all), 'avg') AS mu_avg_pf4, 
+  list_aggregate(list_transform(Muon, x -> x.dxy), 'avg') AS mu_avg_dxy, 
+  list_aggregate(list_transform(Muon, x -> x.dxyerr), 'avg') AS mu_avg_dxyer, 
+  list_aggregate(list_transform(Muon, x -> x.dz), 'avg') AS mu_avg_dz, 
+  list_aggregate(list_transform(Muon, x -> x.dzerr), 'avg') AS mu_avg_dzer, 
+  list_aggregate(list_transform(Muon, x -> x.jetidx), 'avg') AS mu_avg_jet, 
+  list_aggregate(list_transform(Muon, x -> x.genpartidx), 'avg') AS mu_avg_get
+  FROM run2012B_singleMu
+;
\ No newline at end of file
diff --git a/benchmark/realnest/05_list_filter.benchmark b/benchmark/realnest/05_list_filter.benchmark
new file mode 100644
index 000000000000..4663fb133587
--- /dev/null
+++ b/benchmark/realnest/05_list_filter.benchmark
@@ -0,0 +1,28 @@
+# name: benchmark/realnest/05_list_filter.benchmark
+# description: Multiple list_filters
+# group: [realnest]
+
+name list_filters
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT
+    count(*) AS total_rows,
+    sum(len(list_filter(Tau, x -> x.charge < 0))) AS negatives,
+    sum(len(list_filter(Tau, x -> x.charge > 0))) AS positives,
+    sum(len(list_filter(Tau, x -> x.charge = 0))) AS neutral,
+    sum(len(list_filter(Tau, x -> (x.pt % 2) - 1 > 0))) AS odds,
+    sum(len(list_filter(Tau, x -> x.idIsoVLoose != x.idIsoLoose))) AS idIsoMatch,
+    sum(len(list_filter(Muon, x -> x.tightId == true))) AS muon,
+    sum(len(list_filter(Electron, x -> x.mass > x.eta + x.phi))) AS elentron,
+    sum(len(list_filter(Photon, x -> x.mass > 0))) AS photon,
+    sum(len(list_filter(Jet, x -> x.puId != false))) AS jet,
+FROM run2012B_singleMu;
\ No newline at end of file
diff --git a/benchmark/realnest/06_list_filter_on_unnested_structure.benchmark b/benchmark/realnest/06_list_filter_on_unnested_structure.benchmark
new file mode 100644
index 000000000000..4a059e55fcf4
--- /dev/null
+++ b/benchmark/realnest/06_list_filter_on_unnested_structure.benchmark
@@ -0,0 +1,24 @@
+# name: benchmark/realnest/06_list_filter_on_unnested_structure.benchmark
+# description: list_filter on unnested_muon structure
+# group: [realnest]
+
+name list_filter_on_unnested_structure
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT list_filter(
+        [pt, eta, phi, mass, pfRelIso03_all, pfRelIso04_all, dxy, dxyErr, jetIdx, genPartIdx],
+        x -> x > 0.01)
+FROM (
+    SELECT UNNEST(Muon, recursive:=true) AS unnested_muon
+    FROM run2012B_singleMu
+    )
+;
\ No newline at end of file
diff --git a/benchmark/realnest/07_list_unique_on_transformed_and_aggregated_list.benchmark b/benchmark/realnest/07_list_unique_on_transformed_and_aggregated_list.benchmark
new file mode 100644
index 000000000000..a35a70d2aff9
--- /dev/null
+++ b/benchmark/realnest/07_list_unique_on_transformed_and_aggregated_list.benchmark
@@ -0,0 +1,28 @@
+# name: benchmark/realnest/07_list_unique_on_transformed_and_aggregated_list.benchmark
+# description: Creates a list by unnesting and re-aggregating it, then performs list_transform and list_unique on that list
+# group: [realnest]
+
+name list_operations_on_strings
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT list_unique(list_transform(lt, s -> length(s))) 
+FROM (
+    SELECT list(text) AS lt 
+    FROM (
+        SELECT bm.text 
+        FROM (
+            SELECT UNNEST(back_matter) AS bm 
+            FROM cord
+            )
+        )
+    )
+;
\ No newline at end of file
diff --git a/benchmark/realnest/08_count_map_keys.benchmark b/benchmark/realnest/08_count_map_keys.benchmark
new file mode 100644
index 000000000000..0ddd40b19cde
--- /dev/null
+++ b/benchmark/realnest/08_count_map_keys.benchmark
@@ -0,0 +1,23 @@
+# name: benchmark/realnest/08_count_map_keys.benchmark
+# description: Count map keys and aggregate them
+# group: [realnest]
+
+name count_map_keys
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT keys, count(*) mentions 
+FROM (
+    SELECT UNNEST(map_keys(tags)) AS keys 
+    FROM open_street_map
+)
+GROUP BY keys
+ORDER BY mentions DESC;
diff --git a/benchmark/realnest/09_array_agg.benchmark b/benchmark/realnest/09_array_agg.benchmark
new file mode 100644
index 000000000000..e810cf40c04f
--- /dev/null
+++ b/benchmark/realnest/09_array_agg.benchmark
@@ -0,0 +1,22 @@
+# name: benchmark/realnest/09_array_agg.benchmark
+# description: Aggregate nested structs
+# group: [realnest]
+
+name aggregate_nested_structs
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT array_agg(data.entities.hashtags), 
+    array_agg(data.entities.mentions),
+    array_agg(data.entities.urls),
+    array_agg(data.entities.annotations),
+    array_agg(data.entities.cashtags) 
+FROM twitter;
\ No newline at end of file
diff --git a/benchmark/realnest/11_list_sort_reduce_transform.benchmark b/benchmark/realnest/11_list_sort_reduce_transform.benchmark
new file mode 100644
index 000000000000..37a682144b54
--- /dev/null
+++ b/benchmark/realnest/11_list_sort_reduce_transform.benchmark
@@ -0,0 +1,25 @@
+# name: benchmark/realnest/11_list_sort_reduce_transform.benchmark
+# description: Transform, aggregate, reduce and sort a list
+# group: [realnest]
+
+name list_sort_reduce_transform
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT list_sort(
+    array_agg(
+        list_reduce(
+            list_transform(Photon, x -> x.pt),
+        (x, y, z) -> (x + y)^z)
+        )
+    ) AS List
+FROM run2012B_singleMu
+WHERE len(Photon) != 0;
\ No newline at end of file
diff --git a/benchmark/realnest/12_map_list_values.benchmark b/benchmark/realnest/12_map_list_values.benchmark
new file mode 100644
index 000000000000..f0d62b36461d
--- /dev/null
+++ b/benchmark/realnest/12_map_list_values.benchmark
@@ -0,0 +1,22 @@
+# name: benchmark/realnest/12_map_list_values.benchmark
+# description: Map list values
+# group: [realnest]
+
+name map_list_values
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT map(tau_pt, tau_eta),
+    map(jet_pt, jet_eta),
+    map(muon_pt, muon_eta),
+    map(ph_pt, ph_eta)
+FROM singleMu
+ORDER BY ALL DESC;
\ No newline at end of file
diff --git a/benchmark/realnest/13_multi_join_nested_data_with_filtering.benchmark b/benchmark/realnest/13_multi_join_nested_data_with_filtering.benchmark
new file mode 100644
index 000000000000..a1b8037d36da
--- /dev/null
+++ b/benchmark/realnest/13_multi_join_nested_data_with_filtering.benchmark
@@ -0,0 +1,28 @@
+# name: benchmark/realnest/13_multi_join_nested_data_with_filtering.benchmark
+# description: Multiple join conditions and filtering on merged and closed pull requests
+# group: [realnest]
+
+name multi_join_nested_data_with_filtering
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT gh_pull.pull_request.base.repo.language AS language,
+    gh_issue.issue.user.login AS login,
+    gh_pull.pull_request.title AS title,
+    gh_pull.pull_request.html_url AS url
+FROM gh_issue, gh_pull 
+WHERE gh_pull.pull_request.base.repo.owner = gh_issue.issue.user
+    AND gh_pull.pull_request.user = gh_pull.pull_request.base.repo.owner
+    AND gh_issue.issue.assignee = gh_pull.pull_request.base.repo.owner
+    AND gh_pull.pull_request.assignee = gh_pull.pull_request.base.repo.owner
+    AND gh_pull.pull_request.merged = 'true'
+    AND gh_pull.pull_request.state = 'closed'
+ORDER BY language, title;
\ No newline at end of file
diff --git a/benchmark/realnest/14_list_slice.benchmark b/benchmark/realnest/14_list_slice.benchmark
new file mode 100644
index 000000000000..9c556778313d
--- /dev/null
+++ b/benchmark/realnest/14_list_slice.benchmark
@@ -0,0 +1,25 @@
+# name: benchmark/realnest/14_list_slice.benchmark
+# description: Benchmark the list_slice function
+# group: [realnest]
+
+name list_slice
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT list_slice(Jet, 2, 9),
+    list_slice(Jet, 1, 6)[:3:-1],
+    list_slice(Muon, 1, 5),
+    list_slice(Muon, 2, 3)[:-4:-1],
+    list_slice(Photon, 1, 3),
+    list_slice(Photon, 1, 6)[:6:-1],
+    list_slice(Tau, 5, 9),
+    list_slice(Tau, 2, 9)[:-8:-1]
+FROM single_mu_lists;
diff --git a/benchmark/realnest/15_list_sort.benchmark b/benchmark/realnest/15_list_sort.benchmark
new file mode 100644
index 000000000000..cc13199f85d5
--- /dev/null
+++ b/benchmark/realnest/15_list_sort.benchmark
@@ -0,0 +1,27 @@
+# name: benchmark/realnest/15_list_sort.benchmark
+# description: Benchmarks list_sort function
+# group: [realnest]
+
+name list_sort
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT list_sort(Jet, 'ASC'),
+    list_sort(Muon, 'DESC'),
+    list_sort(Muon, 'ASC', 'NULLS FIRST'),
+    list_sort(Muon, 'ASC', 'NULLS LAST'),
+    list_sort(Photon, 'ASC'),
+    list_sort(Photon, 'DESC', 'NULLS FIRST'),
+    list_sort(Photon, 'DESC', 'NULLS LAST'),
+    list_sort(Tau, 'DESC'),
+    list_sort(Tau, 'ASC', 'NULLS FIRST'),
+    list_sort(Tau, 'ASC', 'NULLS LAST')
+FROM single_mu_lists;
\ No newline at end of file
diff --git a/benchmark/realnest/16_most_common_list_aggregates.benchmark b/benchmark/realnest/16_most_common_list_aggregates.benchmark
new file mode 100644
index 000000000000..c7e5f1fb540c
--- /dev/null
+++ b/benchmark/realnest/16_most_common_list_aggregates.benchmark
@@ -0,0 +1,82 @@
+# name: benchmark/realnest/16_most_common_list_aggregates.benchmark
+# description: Combination of the most common list_aggregate functions
+# group: [realnest]
+
+name most_common_list_aggregates
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT 
+  list_aggregate(tau_pt, 'list'),
+  list_aggregate(tau_eta, 'list'),
+  list_aggregate(jet_pt, 'list'),
+  list_aggregate(jet_eta, 'list'),
+  list_aggregate(muon_pt, 'list'),
+  list_aggregate(muon_eta, 'list'),
+  list_aggregate(ph_pt, 'list'),
+  list_aggregate(ph_eta, 'list'),
+  list_aggregate(tau_pt, 'sum'),
+  list_aggregate(tau_eta, 'sum'),
+  list_aggregate(jet_pt, 'sum'),
+  list_aggregate(jet_eta, 'sum'),
+  list_aggregate(muon_pt, 'sum'),
+  list_aggregate(muon_eta, 'sum'),
+  list_aggregate(ph_pt, 'sum'),
+  list_aggregate(ph_eta, 'sum'),
+  list_aggregate(tau_pt, 'min'),
+  list_aggregate(tau_eta, 'min'),
+  list_aggregate(jet_pt, 'min'),
+  list_aggregate(jet_eta, 'min'),
+  list_aggregate(muon_pt, 'min'),
+  list_aggregate(muon_eta, 'min'),
+  list_aggregate(ph_pt, 'min'),
+  list_aggregate(ph_eta, 'min'),
+  list_aggregate(tau_pt, 'max'),
+  list_aggregate(tau_eta, 'max'),
+  list_aggregate(jet_pt, 'max'),
+  list_aggregate(jet_eta, 'max'),
+  list_aggregate(muon_pt, 'max'),
+  list_aggregate(muon_eta, 'max'),
+  list_aggregate(ph_pt, 'max'),
+  list_aggregate(ph_eta, 'max'),
+  list_aggregate(tau_pt, 'count'),
+  list_aggregate(tau_eta, 'count'),
+  list_aggregate(jet_pt, 'count'),
+  list_aggregate(jet_eta, 'count'),
+  list_aggregate(muon_pt, 'count'),
+  list_aggregate(muon_eta, 'count'),
+  list_aggregate(ph_pt, 'count'),
+  list_aggregate(ph_eta, 'count'),
+  list_aggregate(tau_pt, 'string_agg', '|'),
+  list_aggregate(tau_eta, 'string_agg', '|'),
+  list_aggregate(jet_pt, 'string_agg', '|'),
+  list_aggregate(jet_eta, 'string_agg', '|'),
+  list_aggregate(muon_pt, 'string_agg', '|'),
+  list_aggregate(muon_eta, 'string_agg', '|'),
+  list_aggregate(ph_pt, 'string_agg', '|'),
+  list_aggregate(ph_eta, 'string_agg', '|'),
+  list_aggregate(tau_pt, 'avg'),
+  list_aggregate(tau_eta, 'avg'),
+  list_aggregate(jet_pt, 'avg'),
+  list_aggregate(jet_eta, 'avg'),
+  list_aggregate(muon_pt, 'avg'),
+  list_aggregate(muon_eta, 'avg'),
+  list_aggregate(ph_pt, 'avg'),
+  list_aggregate(ph_eta, 'avg'),
+  list_aggregate(tau_pt, 'median'),
+  list_aggregate(tau_eta, 'median'),
+  list_aggregate(jet_pt, 'median'),
+  list_aggregate(jet_eta, 'median'),
+  list_aggregate(muon_pt, 'median'),
+  list_aggregate(muon_eta, 'median'),
+  list_aggregate(ph_pt, 'median'),
+  list_aggregate(ph_eta, 'median') 
+FROM singleMu;
\ No newline at end of file
diff --git a/benchmark/realnest/17_list_aggregates_histogram_stddev_mode.benchmark b/benchmark/realnest/17_list_aggregates_histogram_stddev_mode.benchmark
new file mode 100644
index 000000000000..61d98b806d3e
--- /dev/null
+++ b/benchmark/realnest/17_list_aggregates_histogram_stddev_mode.benchmark
@@ -0,0 +1,42 @@
+# name: benchmark/realnest/17_list_aggregates_histogram_stddev_mode.benchmark
+# description: Combination of list_aggregate functions histogram, stddev, mode
+# group: [realnest]
+
+name list_aggregates_histogram_stddev_mode
+group real_nest
+
+require json
+
+require httpfs
+
+cache real_nest.duckdb
+
+load benchmark/realnest/load.sql
+
+run
+SELECT 
+  list_aggregate(tau_pt, 'stddev'),
+  list_aggregate(tau_eta, 'stddev'),
+  list_aggregate(jet_pt, 'stddev'),
+  list_aggregate(jet_eta, 'stddev'),
+  list_aggregate(muon_pt, 'stddev'),
+  list_aggregate(muon_eta, 'stddev'),
+  list_aggregate(ph_pt, 'stddev'),
+  list_aggregate(ph_eta, 'stddev'),
+  list_aggregate(tau_pt, 'mode'),
+  list_aggregate(tau_eta, 'mode'),
+  list_aggregate(jet_pt, 'mode'),
+  list_aggregate(jet_eta, 'mode'),
+  list_aggregate(muon_pt, 'mode'),
+  list_aggregate(muon_eta, 'mode'),
+  list_aggregate(ph_pt, 'mode'),
+  list_aggregate(ph_eta, 'mode'),
+  list_aggregate(tau_pt, 'histogram'),
+  list_aggregate(tau_eta, 'histogram'),
+  list_aggregate(jet_pt, 'histogram'),
+  list_aggregate(jet_eta, 'histogram'),
+  list_aggregate(muon_pt, 'histogram'),
+  list_aggregate(muon_eta, 'histogram'),
+  list_aggregate(ph_pt, 'histogram'),
+  list_aggregate(ph_eta, 'histogram')  
+FROM singleMu;
\ No newline at end of file
diff --git a/benchmark/realnest/load.sql b/benchmark/realnest/load.sql
new file mode 100644
index 000000000000..de06b949bd57
--- /dev/null
+++ b/benchmark/realnest/load.sql
@@ -0,0 +1,27 @@
+ATTACH 'https://duckdb-blobs.s3.amazonaws.com/data/realnest/cord_10k.duckdb' AS cord (READ_ONLY);
+CREATE TABLE cord AS SELECT * FROM cord.cord;
+ATTACH 'https://duckdb-blobs.s3.amazonaws.com/data/realnest/open_street_map_524k.duckdb' AS osm (READ_ONLY);
+CREATE TABLE open_street_map AS SELECT * FROM osm.open_street_map;
+ATTACH 'https://duckdb-blobs.s3.amazonaws.com/data/realnest/pull_131k.duckdb' AS gh_pull (READ_ONLY);
+CREATE TABLE gh_pull AS SELECT * FROM gh_pull.gh_pull;
+ATTACH 'https://duckdb-blobs.s3.amazonaws.com/data/realnest/issue_131k.duckdb' AS gh_issue (READ_ONLY);
+CREATE TABLE gh_issue AS SELECT * FROM gh_issue.gh_issue;
+ATTACH 'https://duckdb-blobs.s3.amazonaws.com/data/realnest/twitter_131k.duckdb' AS tw (READ_ONLY);
+CREATE TABLE twitter AS SELECT * FROM tw.twitter;
+ATTACH 'https://duckdb-blobs.s3.amazonaws.com/data/realnest/singleMu_524k.duckdb' AS rn_singleMu (READ_ONLY);
+CREATE TABLE run2012B_singleMu AS SELECT * FROM rn_singleMu.run2012B_singleMu;
+CREATE TABLE single_mu_lists AS SELECT * REPLACE(
+    list_resize(Jet, 10, NULL) AS Jet, list_resize(Muon, 10, NULL) AS Muon, 
+    list_resize(Photon, 10, NULL) AS Photon, list_resize(Tau, 10, NULL) AS Tau) 
+FROM rn_singleMu.run2012B_singleMu;
+CREATE OR REPLACE TABLE singleMu AS 
+SELECT 
+    list_distinct(list_transform("Tau", x -> x.pt)) AS tau_pt, list_distinct(list_transform("Tau", x -> x.eta)) AS tau_eta,
+    list_distinct(list_transform("Jet", x -> x.pt)) AS jet_pt, list_distinct(list_transform("Jet", x -> x.eta)) AS jet_eta, 
+    list_distinct(list_transform("Muon", x -> x.pt)) AS muon_pt, list_distinct(list_transform("Muon", x -> x.eta)) AS muon_eta, 
+    list_distinct(list_transform("Photon", x -> x.pt)) AS ph_pt, list_distinct(list_transform("Photon", x -> x.eta)) AS ph_eta
+FROM rn_singleMu.run2012B_singleMu ORDER BY all DESC;
+UPDATE singleMu SET jet_eta = list_resize(jet_eta, len(jet_pt));
+UPDATE singleMu SET muon_eta = list_resize(muon_eta, len(muon_pt));
+UPDATE singleMu SET ph_eta = list_resize(ph_eta, len(ph_pt));
+UPDATE singleMu SET tau_eta = list_resize(tau_eta, len(tau_pt));
\ No newline at end of file
diff --git a/extension/tpcds/dsdgen/answers/sf100/67.csv b/extension/tpcds/dsdgen/answers/sf100/67.csv
index bc31ccae5734..333d6bb0b43e 100644
--- a/extension/tpcds/dsdgen/answers/sf100/67.csv
+++ b/extension/tpcds/dsdgen/answers/sf100/67.csv
@@ -1,101 +1,101 @@
-i_category|i_class|i_brandNULL|i_product_name|d_year|d_qoy|d_moy|s_store_idNULL|sumsales|rk
-NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|32029263.56|5
-NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|64897398.47|4
-NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|130412669.10|3
-NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|255726974.02|2
-NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|101405424479.10|1
-NULL|NULL|NULL|NULL|2000|NULL|NULL|NULL|32029263.56|5
-NULL|NULL|NULL|NULL|2000|1|NULL|NULL|4638714.74|17
-NULL|NULL|NULL|NULL|2000|1|1|NULL|1783708.73|96
-NULL|NULL|NULL|NULL|2000|2|NULL|NULL|4645572.81|16
-NULL|NULL|NULL|NULL|2000|2|4|NULL|1561458.02|98
-NULL|NULL|NULL|NULL|2000|2|5|NULL|1590047.34|97
-NULL|NULL|NULL|NULL|2000|2|6|NULL|1494067.45|100
-NULL|NULL|NULL|NULL|2000|3|NULL|NULL|8690732.06|8
-NULL|NULL|NULL|NULL|2000|3|7|NULL|1528725.34|99
-NULL|NULL|NULL|NULL|2000|3|8|NULL|3598412.10|23
-NULL|NULL|NULL|NULL|2000|3|9|NULL|3563594.62|24
-NULL|NULL|NULL|NULL|2000|4|NULL|NULL|14054243.95|7
-NULL|NULL|NULL|NULL|2000|4|10|NULL|3651929.46|22
-NULL|NULL|NULL|NULL|2000|4|11|NULL|4950352.60|14
-NULL|NULL|NULL|NULL|2000|4|12|NULL|5451961.89|11
-NULL|NULL|amalgedu pack #2|NULL|NULL|NULL|NULL|NULL|1948460.41|84
-NULL|NULL|amalgimporto #2|NULL|NULL|NULL|NULL|NULL|2060499.95|51
-NULL|NULL|amalgscholar #2|NULL|NULL|NULL|NULL|NULL|2915350.58|33
-NULL|NULL|edu packamalg #2|NULL|NULL|NULL|NULL|NULL|2337169.45|38
-NULL|NULL|edu packamalgamalg #17|NULL|NULL|NULL|NULL|NULL|1983663.81|75
-NULL|NULL|edu packamalgamalg #17|NULL|NULL|NULL|NULL|NULL|1983663.81|75
-NULL|NULL|edu packamalgamalg #17|NULL|2000|NULL|NULL|NULL|1983663.81|75
-NULL|NULL|exportiedu pack #1|NULL|NULL|NULL|NULL|NULL|2015173.47|63
-NULL|NULL|exportiedu pack #1|NULL|NULL|NULL|NULL|NULL|2015173.47|63
-NULL|NULL|exportiedu pack #1|NULL|2000|NULL|NULL|NULL|2015173.47|63
-NULL|NULL|exportiedu pack #2|NULL|NULL|NULL|NULL|NULL|1980110.68|79
-NULL|NULL|exportiedu pack #2|NULL|NULL|NULL|NULL|NULL|1980110.68|79
-NULL|NULL|exportiedu pack #2|NULL|2000|NULL|NULL|NULL|1980110.68|79
-NULL|NULL|exportiimporto #2|NULL|NULL|NULL|NULL|NULL|2054391.13|52
-NULL|NULL|importoedu pack #1|NULL|NULL|NULL|NULL|NULL|2017011.96|59
-NULL|NULL|importoedu pack #1|NULL|NULL|NULL|NULL|NULL|2017011.96|59
-NULL|NULL|importoedu pack #1|NULL|2000|NULL|NULL|NULL|2017011.96|59
-NULL|archery|NULL|NULL|NULL|NULL|NULL|NULL|1880685.97|94
-NULL|athletic|NULL|NULL|NULL|NULL|NULL|NULL|3061542.94|28
-NULL|athletic|NULL|NULL|NULL|NULL|NULL|NULL|5210675.89|12
-NULL|baseball|NULL|NULL|NULL|NULL|NULL|NULL|1983963.50|74
-NULL|basketball|NULL|NULL|NULL|NULL|NULL|NULL|1883886.93|93
-NULL|business|NULL|NULL|NULL|NULL|NULL|NULL|2297093.85|39
-NULL|classical|NULL|NULL|NULL|NULL|NULL|NULL|2917057.26|32
-NULL|classical|edu packscholar #2|NULL|NULL|NULL|NULL|NULL|1916841.57|87
-NULL|country|NULL|NULL|NULL|NULL|NULL|NULL|3163375.78|25
-NULL|country|importoscholar #2|NULL|NULL|NULL|NULL|NULL|2148581.27|42
-NULL|country|importoscholar #2|NULL|NULL|NULL|NULL|NULL|2148581.27|42
-NULL|country|importoscholar #2|NULL|2000|NULL|NULL|NULL|2148581.27|42
-NULL|customNULL|NULL|NULL|NULL|NULL|NULL|NULL|2075212.54|50
-NULL|diamonds|NULL|NULL|NULL|NULL|NULL|NULL|1984577.91|73
-NULL|dresses|NULL|NULL|NULL|NULL|NULL|NULL|2076617.17|48
-NULL|dresses|NULL|NULL|NULL|NULL|NULL|NULL|3095482.08|26
-NULL|dresses|NULL|NULL|NULL|NULL|NULL|NULL|6028869.45|9
-NULL|dresses|NULL|NULL|2000|NULL|NULL|NULL|2076617.17|48
-NULL|dresses|amalgamalg #2|NULL|NULL|NULL|NULL|NULL|2918521.76|31
-NULL|earings|NULL|NULL|NULL|NULL|NULL|NULL|1988864.96|70
-NULL|earings|NULL|NULL|NULL|NULL|NULL|NULL|1988864.96|70
-NULL|earings|NULL|NULL|NULL|NULL|NULL|NULL|2003748.82|68
-NULL|earings|NULL|NULL|2000|NULL|NULL|NULL|1988864.96|70
-NULL|fragrances|NULL|NULL|NULL|NULL|NULL|NULL|1983149.33|78
-NULL|fragrances|NULL|NULL|NULL|NULL|NULL|NULL|4894370.20|15
-NULL|fragrances|importoamalg #1|NULL|NULL|NULL|NULL|NULL|1925135.95|86
-NULL|history|NULL|NULL|NULL|NULL|NULL|NULL|1907089.25|89
-NULL|history|NULL|NULL|NULL|NULL|NULL|NULL|1907089.25|89
-NULL|history|NULL|NULL|NULL|NULL|NULL|NULL|2765482.40|37
-NULL|history|NULL|NULL|2000|NULL|NULL|NULL|1907089.25|89
-NULL|infants|NULL|NULL|NULL|NULL|NULL|NULL|2120615.81|46
-NULL|loose stones|NULL|NULL|NULL|NULL|NULL|NULL|1886624.99|92
-NULL|memory|NULL|NULL|NULL|NULL|NULL|NULL|2126286.51|45
-NULL|mens|NULL|NULL|NULL|NULL|NULL|NULL|1966086.96|83
-NULL|mens|NULL|NULL|NULL|NULL|NULL|NULL|2906981.21|35
-NULL|newborn|NULL|NULL|NULL|NULL|NULL|NULL|2885464.55|36
-NULL|newborn|NULL|NULL|NULL|NULL|NULL|NULL|3999371.31|19
-NULL|pants|NULL|NULL|NULL|NULL|NULL|NULL|3899912.48|21
-NULL|pants|exportiimporto #2|NULL|NULL|NULL|NULL|NULL|2024416.72|57
-NULL|pants|exportiimporto #2|NULL|NULL|NULL|NULL|NULL|2960921.19|30
-NULL|pants|exportiimporto #2|NULL|2000|NULL|NULL|NULL|2024416.72|57
-NULL|pendants|NULL|NULL|NULL|NULL|NULL|NULL|1915760.89|88
-NULL|popNULL|NULL|NULL|NULL|NULL|NULL|NULL|1866736.95|95
-NULL|reference|NULL|NULL|NULL|NULL|NULL|NULL|1927519.76|85
-NULL|rockNULL|NULL|NULL|NULL|NULL|NULL|NULL|2221752.90|41
-NULL|rockNULL|NULL|NULL|NULL|NULL|NULL|NULL|2234031.88|40
-NULL|shirts|NULL|NULL|NULL|NULL|NULL|NULL|2005748.24|66
-NULL|shirts|NULL|NULL|NULL|NULL|NULL|NULL|2015374.72|62
-NULL|shirts|NULL|NULL|NULL|NULL|NULL|NULL|3989095.69|20
-NULL|shirts|NULL|NULL|2000|NULL|NULL|NULL|2005748.24|66
-NULL|sports-apparel|NULL|NULL|NULL|NULL|NULL|NULL|2107528.93|47
-NULL|sports-apparel|NULL|NULL|NULL|NULL|NULL|NULL|3055899.02|29
-NULL|swimwear|NULL|NULL|NULL|NULL|NULL|NULL|2912705.57|34
-NULL|swimwear|NULL|NULL|NULL|NULL|NULL|NULL|5986028.72|10
-NULL|swimwear|edu packamalg #1|NULL|NULL|NULL|NULL|NULL|2027301.93|54
-NULL|toddlers|NULL|NULL|NULL|NULL|NULL|NULL|2038611.36|53
-NULL|toddlers|NULL|NULL|NULL|NULL|NULL|NULL|4013880.91|18
-NULL|toddlers|exportiexporti #2|NULL|NULL|NULL|NULL|NULL|1975269.55|82
-NULL|womens|NULL|NULL|NULL|NULL|NULL|NULL|1994814.32|69
-NULL|womens|NULL|NULL|NULL|NULL|NULL|NULL|5074897.40|13
-NULL|womens|amalgedu pack #2|NULL|NULL|NULL|NULL|NULL|2024659.79|55
-NULL|womens|amalgedu pack #2|NULL|NULL|NULL|NULL|NULL|3080083.08|27
-NULL|womens|amalgedu pack #2|NULL|2000|NULL|NULL|NULL|2024659.79|55
+i_category|i_class|i_brand|i_product_name|d_year|d_qoy|d_moy|s_store_id|sumsales|rk
+NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|32029263.56|5
+NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|64897398.47|4
+NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|130412669.10|3
+NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|255726974.02|2
+NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|101405424479.10|1
+NULL|NULL|NULL|NULL|2000|NULL|NULL|NULL|32029263.56|5
+NULL|NULL|NULL|NULL|2000|1|NULL|NULL|4638714.74|17
+NULL|NULL|NULL|NULL|2000|1|1|NULL|1783708.73|96
+NULL|NULL|NULL|NULL|2000|2|NULL|NULL|4645572.81|16
+NULL|NULL|NULL|NULL|2000|2|4|NULL|1561458.02|98
+NULL|NULL|NULL|NULL|2000|2|5|NULL|1590047.34|97
+NULL|NULL|NULL|NULL|2000|2|6|NULL|1494067.45|100
+NULL|NULL|NULL|NULL|2000|3|NULL|NULL|8690732.06|8
+NULL|NULL|NULL|NULL|2000|3|7|NULL|1528725.34|99
+NULL|NULL|NULL|NULL|2000|3|8|NULL|3598412.10|23
+NULL|NULL|NULL|NULL|2000|3|9|NULL|3563594.62|24
+NULL|NULL|NULL|NULL|2000|4|NULL|NULL|14054243.95|7
+NULL|NULL|NULL|NULL|2000|4|10|NULL|3651929.46|22
+NULL|NULL|NULL|NULL|2000|4|11|NULL|4950352.60|14
+NULL|NULL|NULL|NULL|2000|4|12|NULL|5451961.89|11
+NULL|NULL|amalgedu pack #2|NULL|NULL|NULL|NULL|NULL|1948460.41|84
+NULL|NULL|amalgimporto #2|NULL|NULL|NULL|NULL|NULL|2060499.95|51
+NULL|NULL|amalgscholar #2|NULL|NULL|NULL|NULL|NULL|2915350.58|33
+NULL|NULL|edu packamalg #2|NULL|NULL|NULL|NULL|NULL|2337169.45|38
+NULL|NULL|edu packamalgamalg #17|NULL|NULL|NULL|NULL|NULL|1983663.81|75
+NULL|NULL|edu packamalgamalg #17|NULL|NULL|NULL|NULL|NULL|1983663.81|75
+NULL|NULL|edu packamalgamalg #17|NULL|2000|NULL|NULL|NULL|1983663.81|75
+NULL|NULL|exportiedu pack #1|NULL|NULL|NULL|NULL|NULL|2015173.47|63
+NULL|NULL|exportiedu pack #1|NULL|NULL|NULL|NULL|NULL|2015173.47|63
+NULL|NULL|exportiedu pack #1|NULL|2000|NULL|NULL|NULL|2015173.47|63
+NULL|NULL|exportiedu pack #2|NULL|NULL|NULL|NULL|NULL|1980110.68|79
+NULL|NULL|exportiedu pack #2|NULL|NULL|NULL|NULL|NULL|1980110.68|79
+NULL|NULL|exportiedu pack #2|NULL|2000|NULL|NULL|NULL|1980110.68|79
+NULL|NULL|exportiimporto #2|NULL|NULL|NULL|NULL|NULL|2054391.13|52
+NULL|NULL|importoedu pack #1|NULL|NULL|NULL|NULL|NULL|2017011.96|59
+NULL|NULL|importoedu pack #1|NULL|NULL|NULL|NULL|NULL|2017011.96|59
+NULL|NULL|importoedu pack #1|NULL|2000|NULL|NULL|NULL|2017011.96|59
+NULL|archery|NULL|NULL|NULL|NULL|NULL|NULL|1880685.97|94
+NULL|athletic|NULL|NULL|NULL|NULL|NULL|NULL|3061542.94|28
+NULL|athletic|NULL|NULL|NULL|NULL|NULL|NULL|5210675.89|12
+NULL|baseball|NULL|NULL|NULL|NULL|NULL|NULL|1983963.50|74
+NULL|basketball|NULL|NULL|NULL|NULL|NULL|NULL|1883886.93|93
+NULL|business|NULL|NULL|NULL|NULL|NULL|NULL|2297093.85|39
+NULL|classical|NULL|NULL|NULL|NULL|NULL|NULL|2917057.26|32
+NULL|classical|edu packscholar #2|NULL|NULL|NULL|NULL|NULL|1916841.57|87
+NULL|country|NULL|NULL|NULL|NULL|NULL|NULL|3163375.78|25
+NULL|country|importoscholar #2|NULL|NULL|NULL|NULL|NULL|2148581.27|42
+NULL|country|importoscholar #2|NULL|NULL|NULL|NULL|NULL|2148581.27|42
+NULL|country|importoscholar #2|NULL|2000|NULL|NULL|NULL|2148581.27|42
+NULL|custom|NULL|NULL|NULL|NULL|NULL|NULL|2075212.54|50
+NULL|diamonds|NULL|NULL|NULL|NULL|NULL|NULL|1984577.91|73
+NULL|dresses|NULL|NULL|NULL|NULL|NULL|NULL|2076617.17|48
+NULL|dresses|NULL|NULL|NULL|NULL|NULL|NULL|3095482.08|26
+NULL|dresses|NULL|NULL|NULL|NULL|NULL|NULL|6028869.45|9
+NULL|dresses|NULL|NULL|2000|NULL|NULL|NULL|2076617.17|48
+NULL|dresses|amalgamalg #2|NULL|NULL|NULL|NULL|NULL|2918521.76|31
+NULL|earings|NULL|NULL|NULL|NULL|NULL|NULL|1988864.96|70
+NULL|earings|NULL|NULL|NULL|NULL|NULL|NULL|1988864.96|70
+NULL|earings|NULL|NULL|NULL|NULL|NULL|NULL|2003748.82|68
+NULL|earings|NULL|NULL|2000|NULL|NULL|NULL|1988864.96|70
+NULL|fragrances|NULL|NULL|NULL|NULL|NULL|NULL|1983149.33|78
+NULL|fragrances|NULL|NULL|NULL|NULL|NULL|NULL|4894370.20|15
+NULL|fragrances|importoamalg #1|NULL|NULL|NULL|NULL|NULL|1925135.95|86
+NULL|history|NULL|NULL|NULL|NULL|NULL|NULL|1907089.25|89
+NULL|history|NULL|NULL|NULL|NULL|NULL|NULL|1907089.25|89
+NULL|history|NULL|NULL|NULL|NULL|NULL|NULL|2765482.40|37
+NULL|history|NULL|NULL|2000|NULL|NULL|NULL|1907089.25|89
+NULL|infants|NULL|NULL|NULL|NULL|NULL|NULL|2120615.81|46
+NULL|loose stones|NULL|NULL|NULL|NULL|NULL|NULL|1886624.99|92
+NULL|memory|NULL|NULL|NULL|NULL|NULL|NULL|2126286.51|45
+NULL|mens|NULL|NULL|NULL|NULL|NULL|NULL|1966086.96|83
+NULL|mens|NULL|NULL|NULL|NULL|NULL|NULL|2906981.21|35
+NULL|newborn|NULL|NULL|NULL|NULL|NULL|NULL|2885464.55|36
+NULL|newborn|NULL|NULL|NULL|NULL|NULL|NULL|3999371.31|19
+NULL|pants|NULL|NULL|NULL|NULL|NULL|NULL|3899912.48|21
+NULL|pants|exportiimporto #2|NULL|NULL|NULL|NULL|NULL|2024416.72|57
+NULL|pants|exportiimporto #2|NULL|NULL|NULL|NULL|NULL|2960921.19|30
+NULL|pants|exportiimporto #2|NULL|2000|NULL|NULL|NULL|2024416.72|57
+NULL|pendants|NULL|NULL|NULL|NULL|NULL|NULL|1915760.89|88
+NULL|pop|NULL|NULL|NULL|NULL|NULL|NULL|1866736.95|95
+NULL|reference|NULL|NULL|NULL|NULL|NULL|NULL|1927519.76|85
+NULL|rock|NULL|NULL|NULL|NULL|NULL|NULL|2221752.90|41
+NULL|rock|NULL|NULL|NULL|NULL|NULL|NULL|2234031.88|40
+NULL|shirts|NULL|NULL|NULL|NULL|NULL|NULL|2005748.24|66
+NULL|shirts|NULL|NULL|NULL|NULL|NULL|NULL|2015374.72|62
+NULL|shirts|NULL|NULL|NULL|NULL|NULL|NULL|3989095.69|20
+NULL|shirts|NULL|NULL|2000|NULL|NULL|NULL|2005748.24|66
+NULL|sports-apparel|NULL|NULL|NULL|NULL|NULL|NULL|2107528.93|47
+NULL|sports-apparel|NULL|NULL|NULL|NULL|NULL|NULL|3055899.02|29
+NULL|swimwear|NULL|NULL|NULL|NULL|NULL|NULL|2912705.57|34
+NULL|swimwear|NULL|NULL|NULL|NULL|NULL|NULL|5986028.72|10
+NULL|swimwear|edu packamalg #1|NULL|NULL|NULL|NULL|NULL|2027301.93|54
+NULL|toddlers|NULL|NULL|NULL|NULL|NULL|NULL|2038611.36|53
+NULL|toddlers|NULL|NULL|NULL|NULL|NULL|NULL|4013880.91|18
+NULL|toddlers|exportiexporti #2|NULL|NULL|NULL|NULL|NULL|1975269.55|82
+NULL|womens|NULL|NULL|NULL|NULL|NULL|NULL|1994814.32|69
+NULL|womens|NULL|NULL|NULL|NULL|NULL|NULL|5074897.40|13
+NULL|womens|amalgedu pack #2|NULL|NULL|NULL|NULL|NULL|2024659.79|55
+NULL|womens|amalgedu pack #2|NULL|NULL|NULL|NULL|NULL|3080083.08|27
+NULL|womens|amalgedu pack #2|NULL|2000|NULL|NULL|NULL|2024659.79|55
\ No newline at end of file
diff --git a/src/common/extra_type_info.cpp b/src/common/extra_type_info.cpp
index 6c09480c1eb3..54f03447c8a5 100644
--- a/src/common/extra_type_info.cpp
+++ b/src/common/extra_type_info.cpp
@@ -1,4 +1,5 @@
 #include "duckdb/common/extra_type_info.hpp"
+#include "duckdb/common/extra_type_info/enum_type_info.hpp"
 #include "duckdb/common/serializer/deserializer.hpp"
 #include "duckdb/common/enum_util.hpp"
 #include "duckdb/common/numeric_utils.hpp"
@@ -220,50 +221,6 @@ PhysicalType EnumTypeInfo::DictType(idx_t size) {
 	}
 }
 
-template <class T>
-struct EnumTypeInfoTemplated : public EnumTypeInfo {
-	explicit EnumTypeInfoTemplated(Vector &values_insert_order_p, idx_t size_p)
-	    : EnumTypeInfo(values_insert_order_p, size_p) {
-		D_ASSERT(values_insert_order_p.GetType().InternalType() == PhysicalType::VARCHAR);
-
-		UnifiedVectorFormat vdata;
-		values_insert_order.ToUnifiedFormat(size_p, vdata);
-
-		auto data = UnifiedVectorFormat::GetData<string_t>(vdata);
-		for (idx_t i = 0; i < size_p; i++) {
-			auto idx = vdata.sel->get_index(i);
-			if (!vdata.validity.RowIsValid(idx)) {
-				throw InternalException("Attempted to create ENUM type with NULL value");
-			}
-			if (values.count(data[idx]) > 0) {
-				throw InvalidInputException("Attempted to create ENUM type with duplicate value %s",
-				                            data[idx].GetString());
-			}
-			values[data[idx]] = UnsafeNumericCast<T>(i);
-		}
-	}
-
-	static shared_ptr<EnumTypeInfoTemplated> Deserialize(Deserializer &deserializer, uint32_t size) {
-		Vector values_insert_order(LogicalType::VARCHAR, size);
-		auto strings = FlatVector::GetData<string_t>(values_insert_order);
-
-		deserializer.ReadList(201, "values", [&](Deserializer::List &list, idx_t i) {
-			strings[i] = StringVector::AddStringOrBlob(values_insert_order, list.ReadElement<string>());
-		});
-		return make_shared_ptr<EnumTypeInfoTemplated>(values_insert_order, size);
-	}
-
-	const string_map_t<T> &GetValues() const {
-		return values;
-	}
-
-	EnumTypeInfoTemplated(const EnumTypeInfoTemplated &) = delete;
-	EnumTypeInfoTemplated &operator=(const EnumTypeInfoTemplated &) = delete;
-
-private:
-	string_map_t<T> values;
-};
-
 EnumTypeInfo::EnumTypeInfo(Vector &values_insert_order_p, idx_t dict_size_p)
     : ExtraTypeInfo(ExtraTypeInfoType::ENUM_TYPE_INFO), values_insert_order(values_insert_order_p),
       dict_type(EnumDictType::VECTOR_DICT), dict_size(dict_size_p) {
diff --git a/src/execution/operator/csv_scanner/sniffer/csv_sniffer.cpp b/src/execution/operator/csv_scanner/sniffer/csv_sniffer.cpp
index bee31f880eb7..baefcff45fa4 100644
--- a/src/execution/operator/csv_scanner/sniffer/csv_sniffer.cpp
+++ b/src/execution/operator/csv_scanner/sniffer/csv_sniffer.cpp
@@ -41,7 +41,7 @@ void MatchAndReplace(CSVOption<T> &original, CSVOption<T> &sniffed, const string
 		// We verify that the user input matches the sniffed value
 		if (original != sniffed) {
 			error += "CSV Sniffer: Sniffer detected value different than the user input for the " + name;
-			error += " options \n Set: " + original.FormatValue() + " Sniffed: " + sniffed.FormatValue() + "\n";
+			error += " options \n Set: " + original.FormatValue() + ", Sniffed: " + sniffed.FormatValue() + "\n";
 		}
 	} else {
 		// We replace the value of original with the sniffed value
@@ -228,8 +228,8 @@ SnifferResult CSVSniffer::SniffCSV(bool force_match) {
 			if (set_names.size() == names.size()) {
 				for (idx_t i = 0; i < set_columns.Size(); i++) {
 					if (set_names[i] != names[i]) {
-						header_error += "Column at position: " + to_string(i) + " Set name: " + set_names[i] +
-						                " Sniffed Name: " + names[i] + "\n";
+						header_error += "Column at position: " + to_string(i) + ", Set name: " + set_names[i] +
+						                ", Sniffed Name: " + names[i] + "\n";
 						match = false;
 					}
 				}
diff --git a/src/execution/operator/csv_scanner/sniffer/header_detection.cpp b/src/execution/operator/csv_scanner/sniffer/header_detection.cpp
index fd050400ce0e..cf42f56dd3a1 100644
--- a/src/execution/operator/csv_scanner/sniffer/header_detection.cpp
+++ b/src/execution/operator/csv_scanner/sniffer/header_detection.cpp
@@ -114,9 +114,9 @@ bool CSVSniffer::DetectHeaderWithSetColumn(ClientContext &context, vector<Header
 			return false;
 		}
 		if (best_header_row[i].value != (*set_columns.names)[i]) {
-			error << "Header Mismatch at position:" << i << "\n";
-			error << "Expected Name: \"" << (*set_columns.names)[i] << "\".";
-			error << "Actual Name: \"" << best_header_row[i].value << "\"."
+			error << "Header mismatch at position: " << i << "\n";
+			error << "Expected name: \"" << (*set_columns.names)[i] << "\", ";
+			error << "Actual name: \"" << best_header_row[i].value << "\"."
 			      << "\n";
 			has_header = false;
 			break;
diff --git a/src/execution/operator/csv_scanner/util/csv_reader_options.cpp b/src/execution/operator/csv_scanner/util/csv_reader_options.cpp
index 21f910ece87a..4ec6541ae322 100644
--- a/src/execution/operator/csv_scanner/util/csv_reader_options.cpp
+++ b/src/execution/operator/csv_scanner/util/csv_reader_options.cpp
@@ -404,7 +404,7 @@ string CSVReaderOptions::ToString(const string &current_file_path) const {
 	auto &skip_rows = dialect_options.skip_rows;
 
 	auto &header = dialect_options.header;
-	string error = "  file=" + current_file_path + "\n  ";
+	string error = "  file = " + current_file_path + "\n  ";
 	// Let's first print options that can either be set by the user or by the sniffer
 	// delimiter
 	error += FormatOptionLine("delimiter", delimiter);
@@ -427,13 +427,13 @@ string CSVReaderOptions::ToString(const string &current_file_path) const {
 
 	// Now we do options that can only be set by the user, that might hold some general significance
 	// null padding
-	error += "null_padding=" + std::to_string(null_padding) + "\n  ";
+	error += "null_padding = " + std::to_string(null_padding) + "\n  ";
 	// sample_size
-	error += "sample_size=" + std::to_string(sample_size_chunks * STANDARD_VECTOR_SIZE) + "\n  ";
+	error += "sample_size = " + std::to_string(sample_size_chunks * STANDARD_VECTOR_SIZE) + "\n  ";
 	// ignore_errors
-	error += "ignore_errors=" + ignore_errors.FormatValue() + "\n  ";
+	error += "ignore_errors = " + ignore_errors.FormatValue() + "\n  ";
 	// all_varchar
-	error += "all_varchar=" + std::to_string(all_varchar) + "\n";
+	error += "all_varchar = " + std::to_string(all_varchar) + "\n";
 
 	// Add information regarding sniffer mismatches (if any)
 	error += sniffer_user_mismatch_error;
diff --git a/src/include/duckdb/common/extra_type_info/enum_type_info.hpp b/src/include/duckdb/common/extra_type_info/enum_type_info.hpp
new file mode 100644
index 000000000000..3949caa8bf04
--- /dev/null
+++ b/src/include/duckdb/common/extra_type_info/enum_type_info.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "duckdb/common/extra_type_info.hpp"
+#include "duckdb/common/serializer/deserializer.hpp"
+#include "duckdb/common/string_map_set.hpp"
+
+namespace duckdb {
+
+template <class T>
+struct EnumTypeInfoTemplated : public EnumTypeInfo {
+	explicit EnumTypeInfoTemplated(Vector &values_insert_order_p, idx_t size_p)
+	    : EnumTypeInfo(values_insert_order_p, size_p) {
+		D_ASSERT(values_insert_order_p.GetType().InternalType() == PhysicalType::VARCHAR);
+
+		UnifiedVectorFormat vdata;
+		values_insert_order.ToUnifiedFormat(size_p, vdata);
+
+		auto data = UnifiedVectorFormat::GetData<string_t>(vdata);
+		for (idx_t i = 0; i < size_p; i++) {
+			auto idx = vdata.sel->get_index(i);
+			if (!vdata.validity.RowIsValid(idx)) {
+				throw InternalException("Attempted to create ENUM type with NULL value");
+			}
+			if (values.count(data[idx]) > 0) {
+				throw InvalidInputException("Attempted to create ENUM type with duplicate value %s",
+				                            data[idx].GetString());
+			}
+			values[data[idx]] = UnsafeNumericCast<T>(i);
+		}
+	}
+
+	static shared_ptr<EnumTypeInfoTemplated> Deserialize(Deserializer &deserializer, uint32_t size) {
+		Vector values_insert_order(LogicalType::VARCHAR, size);
+		auto strings = FlatVector::GetData<string_t>(values_insert_order);
+
+		deserializer.ReadList(201, "values", [&](Deserializer::List &list, idx_t i) {
+			strings[i] = StringVector::AddStringOrBlob(values_insert_order, list.ReadElement<string>());
+		});
+		return make_shared_ptr<EnumTypeInfoTemplated>(values_insert_order, size);
+	}
+
+	const string_map_t<T> &GetValues() const {
+		return values;
+	}
+
+	EnumTypeInfoTemplated(const EnumTypeInfoTemplated &) = delete;
+	EnumTypeInfoTemplated &operator=(const EnumTypeInfoTemplated &) = delete;
+
+private:
+	string_map_t<T> values;
+};
+
+} // namespace duckdb
diff --git a/src/include/duckdb/storage/table/segment_tree.hpp b/src/include/duckdb/storage/table/segment_tree.hpp
index e267d2e351eb..218cdac9b16f 100644
--- a/src/include/duckdb/storage/table/segment_tree.hpp
+++ b/src/include/duckdb/storage/table/segment_tree.hpp
@@ -145,6 +145,7 @@ class SegmentTree {
 		}
 		SegmentNode<T> node;
 		segment->index = nodes.size();
+		segment->next = nullptr;
 		node.row_start = segment->start;
 		node.node = std::move(segment);
 		nodes.push_back(std::move(node));
diff --git a/src/storage/table/row_group_collection.cpp b/src/storage/table/row_group_collection.cpp
index b0eb5022f75b..4dfb194921b6 100644
--- a/src/storage/table/row_group_collection.cpp
+++ b/src/storage/table/row_group_collection.cpp
@@ -962,8 +962,8 @@ unique_ptr<CheckpointTask> RowGroupCollection::GetCheckpointTask(CollectionCheck
 }
 
 void RowGroupCollection::Checkpoint(TableDataWriter &writer, TableStatistics &global_stats) {
-	auto segments = row_groups->MoveSegments();
 	auto l = row_groups->Lock();
+	auto segments = row_groups->MoveSegments(l);
 
 	CollectionCheckpointState checkpoint_state(*this, writer, segments, global_stats);
 


Test patch:
diff --git a/test/sql/storage/delete/delete_final_row_group.test b/test/sql/storage/delete/delete_final_row_group.test
new file mode 100644
index 000000000000..6dba3aca5923
--- /dev/null
+++ b/test/sql/storage/delete/delete_final_row_group.test
@@ -0,0 +1,42 @@
+# name: test/sql/storage/delete/delete_final_row_group.test
+# description: Test deleting the final row groups of a table
+# group: [delete]
+
+load __TEST_DIR__/delete_final_row_group.db
+
+statement ok
+CREATE TABLE integers AS SELECT * FROM range(0, 10000000) t(i);
+
+query I
+DELETE FROM integers WHERE i>=5000000
+----
+5000000
+
+query II
+SELECT COUNT(*), SUM(i) FROM integers
+----
+5000000	12499997500000
+
+
+statement ok
+ALTER TABLE integers ADD COLUMN j INTEGER
+
+query III
+SELECT COUNT(*), SUM(i), SUM(j) FROM integers
+----
+5000000	12499997500000	NULL
+
+statement ok
+UPDATE integers SET j=i+1
+
+query III
+SELECT COUNT(*), SUM(i), SUM(j) FROM integers
+----
+5000000	12499997500000	12500002500000
+
+restart
+
+query III
+SELECT COUNT(*), SUM(i), SUM(j) FROM integers
+----
+5000000	12499997500000	12500002500000
diff --git a/test/sqlite/sqllogic_command.cpp b/test/sqlite/sqllogic_command.cpp
index eb7636362900..527b91c6d115 100644
--- a/test/sqlite/sqllogic_command.cpp
+++ b/test/sqlite/sqllogic_command.cpp
@@ -492,14 +492,6 @@ void UnzipCommand::ExecuteInternal(ExecuteContext &context) const {
 		throw CatalogException("Cannot open the file \"%s\"", input_path);
 	}
 
-	// read the compressed data from the file
-	int64_t file_size = vfs.GetFileSize(*compressed_file_handle);
-	std::unique_ptr<char[]> compressed_buffer(new char[BUFFER_SIZE]);
-	int64_t bytes_read = vfs.Read(*compressed_file_handle, compressed_buffer.get(), BUFFER_SIZE);
-	if (bytes_read < file_size) {
-		throw CatalogException("Cannot read the file \"%s\"", input_path);
-	}
-
 	// output
 	FileOpenFlags out_flags(FileOpenFlags::FILE_FLAGS_FILE_CREATE | FileOpenFlags::FILE_FLAGS_WRITE);
 	auto output_file = vfs.OpenFile(extraction_path, out_flags);
@@ -507,9 +499,15 @@ void UnzipCommand::ExecuteInternal(ExecuteContext &context) const {
 		throw CatalogException("Cannot open the file \"%s\"", extraction_path);
 	}
 
-	int64_t bytes_written = vfs.Write(*output_file, compressed_buffer.get(), BUFFER_SIZE);
-	if (bytes_written < file_size) {
-		throw CatalogException("Cannot write the file \"%s\"", extraction_path);
+	// read the compressed data from the file
+	while (true) {
+		std::unique_ptr<char[]> compressed_buffer(new char[BUFFER_SIZE]);
+		int64_t bytes_read = vfs.Read(*compressed_file_handle, compressed_buffer.get(), BUFFER_SIZE);
+		if (bytes_read == 0) {
+			break;
+		}
+
+		vfs.Write(*output_file, compressed_buffer.get(), bytes_read);
 	}
 }