Skip to content

Commit 4d18b9d

Browse files
authored
Merge pull request #13776 from Mytherin/expressiondepth
Make binder expression depth limit use `max_expression_depth`
2 parents c494072 + a3a1824 commit 4d18b9d

File tree

6 files changed

+27
-14
lines changed

6 files changed

+27
-14
lines changed

src/include/duckdb/planner/expression_binder.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ class ExpressionBinder {
154154
static LogicalType GetExpressionReturnType(const Expression &expr);
155155

156156
private:
157-
//! Maximum stack depth
158-
static constexpr const idx_t MAXIMUM_STACK_DEPTH = 128;
159157
//! Current stack depth
160158
idx_t stack_depth = DConstants::INVALID_INDEX;
161159

@@ -204,6 +202,8 @@ class ExpressionBinder {
204202
virtual BindResult BindUnnest(FunctionExpression &expr, idx_t depth, bool root_expression);
205203
virtual BindResult BindMacro(FunctionExpression &expr, ScalarMacroCatalogEntry &macro, idx_t depth,
206204
unique_ptr<ParsedExpression> &expr_ptr);
205+
void UnfoldMacroExpression(FunctionExpression &function, ScalarMacroCatalogEntry &macro_func,
206+
unique_ptr<ParsedExpression> &expr);
207207

208208
virtual string UnsupportedAggregateMessage();
209209
virtual string UnsupportedUnnestMessage();

src/planner/binder/expression/bind_macro_expression.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ void ExpressionBinder::ReplaceMacroParameters(unique_ptr<ParsedExpression> &expr
9999
*expr, [&](unique_ptr<ParsedExpression> &child) { ReplaceMacroParameters(child, lambda_params); });
100100
}
101101

102-
BindResult ExpressionBinder::BindMacro(FunctionExpression &function, ScalarMacroCatalogEntry &macro_func, idx_t depth,
103-
unique_ptr<ParsedExpression> &expr) {
102+
void ExpressionBinder::UnfoldMacroExpression(FunctionExpression &function, ScalarMacroCatalogEntry &macro_func,
103+
unique_ptr<ParsedExpression> &expr) {
104104
// validate the arguments and separate positional and default arguments
105105
vector<unique_ptr<ParsedExpression>> positionals;
106106
unordered_map<string, unique_ptr<ParsedExpression>> defaults;
@@ -143,6 +143,14 @@ BindResult ExpressionBinder::BindMacro(FunctionExpression &function, ScalarMacro
143143
// now replace the parameters
144144
vector<unordered_set<string>> lambda_params;
145145
ReplaceMacroParameters(expr, lambda_params);
146+
}
147+
148+
BindResult ExpressionBinder::BindMacro(FunctionExpression &function, ScalarMacroCatalogEntry &macro_func, idx_t depth,
149+
unique_ptr<ParsedExpression> &expr) {
150+
auto stack_checker = StackCheck(*expr, 3);
151+
152+
// unfold the macro expression
153+
UnfoldMacroExpression(function, macro_func, expr);
146154

147155
// bind the unfolded macro
148156
return BindExpression(expr, depth);

src/planner/expression_binder.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "duckdb/planner/expression/list.hpp"
88
#include "duckdb/planner/expression_iterator.hpp"
99
#include "duckdb/common/operator/cast_operators.hpp"
10+
#include "duckdb/main/client_config.hpp"
1011

1112
namespace duckdb {
1213

@@ -36,18 +37,21 @@ ExpressionBinder::~ExpressionBinder() {
3637
}
3738

3839
void ExpressionBinder::InitializeStackCheck() {
40+
static constexpr idx_t INITIAL_DEPTH = 5;
3941
if (binder.HasActiveBinder()) {
40-
stack_depth = binder.GetActiveBinder().stack_depth;
42+
stack_depth = binder.GetActiveBinder().stack_depth + INITIAL_DEPTH;
4143
} else {
42-
stack_depth = 0;
44+
stack_depth = INITIAL_DEPTH;
4345
}
4446
}
4547

4648
StackChecker<ExpressionBinder> ExpressionBinder::StackCheck(const ParsedExpression &expr, idx_t extra_stack) {
4749
D_ASSERT(stack_depth != DConstants::INVALID_INDEX);
48-
if (stack_depth + extra_stack >= MAXIMUM_STACK_DEPTH) {
49-
throw BinderException("Maximum recursion depth exceeded (Maximum: %llu) while binding \"%s\"",
50-
MAXIMUM_STACK_DEPTH, expr.ToString());
50+
auto &options = ClientConfig::GetConfig(context);
51+
if (stack_depth + extra_stack >= options.max_expression_depth) {
52+
throw BinderException("Max expression depth limit of %lld exceeded. Use \"SET max_expression_depth TO x\" to "
53+
"increase the maximum expression depth.",
54+
options.max_expression_depth);
5155
}
5256
return StackChecker<ExpressionBinder>(*this, extra_stack);
5357
}

test/sql/catalog/function/test_recursive_macro.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ CREATE MACRO "sum"(x) AS (CASE WHEN sum(x) IS NULL THEN 0 ELSE sum(x) END);
1111
statement error
1212
SELECT sum(1);
1313
----
14-
Binder Error: Maximum recursion depth exceeded
14+
Max expression depth limit
1515

1616
statement error
1717
SELECT sum(1) WHERE 42=0
1818
----
19-
Binder Error: Maximum recursion depth exceeded
19+
Max expression depth limit
2020

2121
statement ok
2222
DROP MACRO sum

test/sql/catalog/function/test_recursive_macro_no_dependency.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ CREATE MACRO "sum"(x) AS (CASE WHEN sum(x) IS NULL THEN 0 ELSE sum(x) END);
88
statement error
99
SELECT sum(1);
1010
----
11-
Binder Error: Maximum recursion depth exceeded
11+
Max expression depth limit
1212

1313
statement error
1414
SELECT sum(1) WHERE 42=0
1515
----
16-
Binder Error: Maximum recursion depth exceeded
16+
Max expression depth limit
1717

1818
statement ok
1919
DROP MACRO sum

test/sql/parser/expression_depth_limit.test

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ statement ok
66
SELECT (1+(1+(1+(1+(1+(1+(1+1)))))));
77

88
statement ok
9-
SET max_expression_depth TO 3;
9+
SET max_expression_depth TO 7;
1010

1111
statement error
1212
SELECT (1+(1+(1+(1+(1+(1+(1+1)))))));
1313
----
14+
expression depth limit
1415

1516
statement ok
1617
SET max_expression_depth TO 1000;

0 commit comments

Comments
 (0)