From af66cdc7480c1f56d4ca857c10b46aebf0454958 Mon Sep 17 00:00:00 2001 From: Alok Subbarao Date: Thu, 24 Sep 2026 11:22:45 -0700 Subject: [PATCH 1/3] Fix function extraction in subqueries --- src/parse_functions.cpp | 56 +++++++++++++++++++ .../parse_function_names.test | 24 +++++++- .../scalar_functions/parse_functions.test | 24 +++++++- 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/src/parse_functions.cpp b/src/parse_functions.cpp index 394a7d7..728cb43 100644 --- a/src/parse_functions.cpp +++ b/src/parse_functions.cpp @@ -5,9 +5,13 @@ #include "duckdb/parser/query_node/cte_node.hpp" #include "duckdb/parser/query_node/select_node.hpp" #include "duckdb/parser/expression/function_expression.hpp" +#include "duckdb/parser/expression/subquery_expression.hpp" #include "duckdb/parser/expression/window_expression.hpp" #include "duckdb/parser/parsed_expression_iterator.hpp" #include "duckdb/parser/result_modifier.hpp" +#include "duckdb/parser/tableref/joinref.hpp" +#include "duckdb/parser/tableref/subqueryref.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" #include "duckdb/function/scalar/nested_functions.hpp" @@ -73,6 +77,8 @@ static unique_ptr ParseFunctionsInit(ClientContext &co return make_uniq(); } +static void ExtractFunctionsFromQueryNode(const QueryNode &node, std::vector &results); + class FunctionExtractor { public: static void ExtractFromExpression(const ParsedExpression &expr, @@ -144,6 +150,14 @@ class FunctionExtractor { if (window_expr.filter_expr) { ExtractFromExpression(*window_expr.filter_expr, results, FunctionContext::Nested); } + } else if (expr.expression_class == ExpressionClass::SUBQUERY) { + auto &subquery = (SubqueryExpression &)expr; + if (subquery.child) { + ExtractFromExpression(*subquery.child, results, context); + } + if (subquery.subquery && subquery.subquery->node) { + ExtractFunctionsFromQueryNode(*subquery.subquery->node, results); + } } else { // For non-function expressions, preserve the current context ParsedExpressionIterator::EnumerateChildren(expr, [&](const ParsedExpression &child) { @@ -163,6 +177,44 @@ class FunctionExtractor { } }; +static void ExtractFunctionsFromRef(const TableRef &ref, std::vector &results) { + switch (ref.type) { + case TableReferenceType::JOIN: { + auto &join = (JoinRef &)ref; + if (join.left) { + ExtractFunctionsFromRef(*join.left, results); + } + if (join.right) { + ExtractFunctionsFromRef(*join.right, results); + } + if (join.condition) { + FunctionExtractor::ExtractFromExpression(*join.condition, results, FunctionContext::Join); + } + break; + } + case TableReferenceType::SUBQUERY: { + auto &subquery = (SubqueryRef &)ref; + if (subquery.subquery && subquery.subquery->node) { + ExtractFunctionsFromQueryNode(*subquery.subquery->node, results); + } + break; + } + case TableReferenceType::TABLE_FUNCTION: { + auto &table_function = (TableFunctionRef &)ref; + if (table_function.function) { + ParsedExpressionIterator::EnumerateChildren(*table_function.function, [&](const ParsedExpression &child) { + FunctionExtractor::ExtractFromExpression(child, results, FunctionContext::Nested); + }); + } + if (table_function.subquery && table_function.subquery->node) { + ExtractFunctionsFromQueryNode(*table_function.subquery->node, results); + } + break; + } + default: + break; + } +} static void ExtractFunctionsFromQueryNode(const QueryNode &node, std::vector &results) { if (node.type == QueryNodeType::SELECT_NODE) { @@ -202,6 +254,10 @@ static void ExtractFunctionsFromQueryNode(const QueryNode &node, std::vector Date: Sun, 4 Oct 2026 14:31:09 -0700 Subject: [PATCH 2/3] ci: work around Windows test-runner quoting bug in extension-ci-tools extension-ci-tools <= v1.5.x defines TEST_PATH with baked-in quotes (TEST_PATH="/test/unittest"), so 'make test_release' invokes ./build/release/"/test/unittest", which fails with Error 127 on Windows (Git Bash) before the test binary ever runs. Fixed upstream in v2.0-cyanoptera via the RUN_TEST macro; override test_release_internal here until ci_tools can move past v1.5.x. Identical to the stock recipe on POSIX. --- Makefile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d03b95c..1813781 100644 --- a/Makefile +++ b/Makefile @@ -5,4 +5,14 @@ EXT_NAME=parser_tools EXT_CONFIG=${PROJ_DIR}extension_config.cmake # Include the Makefile from extension-ci-tools -include extension-ci-tools/makefiles/duckdb_extension.Makefile \ No newline at end of file +include extension-ci-tools/makefiles/duckdb_extension.Makefile + +# Workaround for a quoting bug in extension-ci-tools <= v1.5.x: TEST_PATH is +# defined with baked-in quotes (TEST_PATH="/test/unittest"), so the test +# invocation becomes ./build/release/"/test/unittest", which fails with +# Error 127 on Windows (Git Bash) — the test binary never runs. Fixed +# upstream in v2.0-cyanoptera via the RUN_TEST macro; override here until +# ci_tools can move past v1.5.x. (On POSIX this is identical to the stock +# recipe: ./build/release//test/unittest.) +test_release_internal: + ./build/release/test/unittest "$(TESTS_BASE_DIRECTORY)*" From 5361990e5e2b4cfb62a60a06da763c4edcc7372c Mon Sep 17 00:00:00 2001 From: Alok Subbarao <96636525+asubbarao@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:04:31 -0700 Subject: [PATCH 3/3] ci(windows): skip test execution on the vs2019 static leg The extension-ci-tools workflow hardcodes vcvars64.bat under "C:\Program Files\Microsoft Visual Studio\2022\Enterprise", which no longer exists on current windows-latest runners. The call fails with "The system cannot find the path specified", CMake then silently falls back to a stray GCC 15.2.0, and the resulting unittest binary cannot be launched from Git Bash (Error 127, deterministic across the 2026-09-24 and 2026-10-04 runs). This was misdiagnosed earlier as a test-harness quoting bug; the invoked command line is byte-identical on the passing mingw job. Set SKIP_TESTS=1 for windows_amd64 (before the ci-tools include, which reads it at include time) until upstream fixes the VS path. Windows coverage is retained via windows_amd64_mingw, where the full suite (11 tests / 435 assertions) passes. --- Makefile | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 1813781..f0bed15 100644 --- a/Makefile +++ b/Makefile @@ -4,15 +4,24 @@ PROJ_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) EXT_NAME=parser_tools EXT_CONFIG=${PROJ_DIR}extension_config.cmake +# Windows vs2019 static leg: the extension-ci-tools workflow's vcvars64.bat +# path (VS2022 Enterprise) no longer exists on current windows-latest +# runners, so CMake silently falls back to GCC and the built unittest binary +# cannot be launched from Git Bash (Error 127, deterministic across runs). +# Skip test execution on windows_amd64 only; Windows coverage is retained via +# windows_amd64_mingw, where the same suite passes. Re-enable once upstream +# fixes the VS path. (Must precede the ci-tools include: SKIP_TESTS is read +# at include time.) +ifeq ($(DUCKDB_PLATFORM),windows_amd64) +SKIP_TESTS=1 +endif + # Include the Makefile from extension-ci-tools include extension-ci-tools/makefiles/duckdb_extension.Makefile -# Workaround for a quoting bug in extension-ci-tools <= v1.5.x: TEST_PATH is -# defined with baked-in quotes (TEST_PATH="/test/unittest"), so the test -# invocation becomes ./build/release/"/test/unittest", which fails with -# Error 127 on Windows (Git Bash) — the test binary never runs. Fixed -# upstream in v2.0-cyanoptera via the RUN_TEST macro; override here until -# ci_tools can move past v1.5.x. (On POSIX this is identical to the stock -# recipe: ./build/release//test/unittest.) +# Override the test invocation: the stock v1.4.4/v1.5.x recipe bakes quotes +# into TEST_PATH ("./build/release/\"/test/unittest\""), which is fragile +# under Windows (Git Bash). This form is identical on POSIX and verified +# working on the mingw Windows job. test_release_internal: ./build/release/test/unittest "$(TESTS_BASE_DIRECTORY)*"