From f09f80b4a907411953de9ffd14f1d37812bbc388 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 19 Sep 2026 20:22:56 -0700 Subject: [PATCH] Fix shadow-table scan link and add SQL pushdown coverage Capture the attached entry pointer before moving it into the catalog: reading it back from the moved-from unique_ptr always yielded null, so shadow node entries never exposed their scan function and no Cypher query over attached DuckDB node tables could plan a table-function scan (which also silently disabled all foreign join pushdown). Add pushdown_graph.db fixture plus sql_pushdown.test covering 1-hop, 2-hop with node/edge filters, aggregation + ORDER BY, and recursive-CTE pushdown. --- duckdb/src/catalog/duckdb_catalog.cpp | 6 +- duckdb/test/test_files/pushdown_graph.db | Bin 0 -> 3682304 bytes duckdb/test/test_files/sql_pushdown.test | 130 +++++++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 duckdb/test/test_files/pushdown_graph.db create mode 100644 duckdb/test/test_files/sql_pushdown.test diff --git a/duckdb/src/catalog/duckdb_catalog.cpp b/duckdb/src/catalog/duckdb_catalog.cpp index 66496160..f3fdca6e 100644 --- a/duckdb/src/catalog/duckdb_catalog.cpp +++ b/duckdb/src/catalog/duckdb_catalog.cpp @@ -137,8 +137,12 @@ void DuckDBCatalog::createForeignTable(const std::string& tableName) { for (auto& definition : extraInfo->propertyDefinitions) { tableEntry->addProperty(definition); } + // NB: capture the raw pointer before moving: the catalog takes ownership of the + // entry, so the pointer stays valid, while the moved-from unique_ptr is null. + // (Reading it after the move wired a null referencedEntry, which silently disabled + // scan-function planning and therefore all SQL pushdown over attached node tables.) + auto* attachedEntry = tableEntry.get(); tables->createEntry(&transaction::DUMMY_TRANSACTION, std::move(tableEntry)); - auto attachedEntry = tableEntry.get(); // Create another for main catalog for traversal support auto primaryKeyName = extraInfo->propertyDefinitions[0].getName(); diff --git a/duckdb/test/test_files/pushdown_graph.db b/duckdb/test/test_files/pushdown_graph.db new file mode 100644 index 0000000000000000000000000000000000000000..39705562426187dbface7bad08b5d5e02516b175 GIT binary patch literal 3682304 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 z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oRXK!0*5F`7gfb_3Qt$RHn3CuIJ?;W<@$r=x;LFN*opuF0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 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 z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1P)f<)!R@0^4hmP@Qu5BlFiEf#SrRgvpQadSL^EdeEa--D}PZLW<`Ji z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PB~0fmiPN z*yCUN(T}g+XjuplAV6Srfh=rwzYR3X-Mahi=(=K<9f6hV!UNv$F0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAJE`dL}_JLde=7A5td81_^K!5;&(FL-w z)qR6*l)H8J+0k{yFnNJfWrMACx8u;e-*Y%<-;=K!DI6bxmFhZMTJF4*YFV*Yy>E0L zvrT{i0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ t009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+0D(gh_gZy literal 0 HcmV?d00001 diff --git a/duckdb/test/test_files/sql_pushdown.test b/duckdb/test/test_files/sql_pushdown.test new file mode 100644 index 00000000..a7eec91d --- /dev/null +++ b/duckdb/test/test_files/sql_pushdown.test @@ -0,0 +1,130 @@ +-DATASET CSV empty + +# SQL pushdown over attached DuckDB graph tables (fixture: pushdown_graph.db). +# +# node_person(id, name, age): Alice/35, Bob/25, Carol/45, Dave/28 +# node_city(id, name): NYC(10), SF(11) +# rel_knows(src_id, dst_id, since, weight): Alice->Bob/2020, Bob->Carol/2021, +# Alice->Carol/2019, Carol->Dave/2022 +# rel_likes(src_id, dst_id, score): Alice->Bob/5, Bob->Carol/8, Carol->Dave/3 +# rel_livesin(src_id, dst_id, since): Alice->NYC, Bob->SF, Carol->NYC +# +# All MATCH traversals below run over `rel_*` tables. Local (non-pushed) +# traversal over such tables errors out ("foreign keys cannot be interpreted +# as node offsets"), so every passing result here proves the pattern was +# pushed down to SQL. + +-- + +-CASE OneHopPushdownBaseline +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION duckdb +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/duckdb/test/test_files/pushdown_graph.db' AS g (DBTYPE DUCKDB); +---- 1 +Attached database successfully. +-STATEMENT USE g; +---- ok +-STATEMENT MATCH (a:node_person)-[r:rel_knows]->(b:node_person) RETURN a.name, b.name ORDER BY a.name, b.name; +---- 4 +Alice|Bob +Alice|Carol +Bob|Carol +Carol|Dave +-STATEMENT DETACH g; +---- ok + +-CASE TwoHopNodeFilterPushdown +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION duckdb +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/duckdb/test/test_files/pushdown_graph.db' AS g (DBTYPE DUCKDB); +---- 1 +Attached database successfully. +-STATEMENT USE g; +---- ok +-STATEMENT MATCH (a:node_person)-[r1:rel_knows]->(b:node_person)-[r2:rel_likes]->(c:node_person) WHERE a.age > 30 RETURN a.name, b.name, c.name ORDER BY a.name, b.name, c.name; +---- 2 +Alice|Bob|Carol +Alice|Carol|Dave +-STATEMENT DETACH g; +---- ok + +-CASE TwoHopEdgeFilterPushdown +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION duckdb +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/duckdb/test/test_files/pushdown_graph.db' AS g (DBTYPE DUCKDB); +---- 1 +Attached database successfully. +-STATEMENT USE g; +---- ok +-STATEMENT MATCH (a:node_person)-[r1:rel_knows]->(b:node_person)-[r2:rel_likes]->(c:node_person) WHERE r1.since >= 2020 AND r2.score > 4 RETURN a.name, c.name; +---- 1 +Alice|Carol +-STATEMENT DETACH g; +---- ok + +-CASE TwoHopMixedNodeLabelsPushdown +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION duckdb +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/duckdb/test/test_files/pushdown_graph.db' AS g (DBTYPE DUCKDB); +---- 1 +Attached database successfully. +-STATEMENT USE g; +---- ok +-STATEMENT MATCH (a:node_person)-[r1:rel_knows]->(b:node_person)-[r2:rel_livesin]->(c:node_city) RETURN a.name, c.name ORDER BY a.name, c.name; +---- 3 +Alice|NYC +Alice|SF +Bob|NYC +-STATEMENT DETACH g; +---- ok + +-CASE AggregationOrderByPushdown +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION duckdb +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/duckdb/test/test_files/pushdown_graph.db' AS g (DBTYPE DUCKDB); +---- 1 +Attached database successfully. +-STATEMENT USE g; +---- ok +-STATEMENT MATCH (a:node_person)-[r:rel_knows]->(b:node_person) RETURN a.name, count(*) AS cnt ORDER BY cnt DESC, a.name; +---- 3 +Alice|2 +Bob|1 +Carol|1 +-STATEMENT DETACH g; +---- ok + +-CASE RecursiveCTEPushdown +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION duckdb +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/duckdb/test/test_files/pushdown_graph.db' AS g (DBTYPE DUCKDB); +---- 1 +Attached database successfully. +-STATEMENT USE g; +---- ok +-STATEMENT MATCH (a:node_person)-[e:rel_knows*1..3]->(b:node_person) RETURN b.name ORDER BY b.name; +---- 8 +Bob +Carol +Carol +Carol +Dave +Dave +Dave +Dave +-STATEMENT DETACH g; +---- ok + +-CASE RecursiveEdgeFilterPushdown +-SKIP_FSM_LEAK_CHECK +-LOAD_DYNAMIC_EXTENSION duckdb +-STATEMENT ATTACH '${LBUG_ROOT_DIRECTORY}/extension/duckdb/test/test_files/pushdown_graph.db' AS g (DBTYPE DUCKDB); +---- 1 +Attached database successfully. +-STATEMENT USE g; +---- ok +-STATEMENT MATCH (a:node_person)-[e:rel_knows*1..2 {since: 2020}]->(b:node_person) RETURN b.name ORDER BY b.name; +---- 1 +Bob +-STATEMENT DETACH g; +---- ok