duckdb 0.6.2-dev1097.0 → 0.6.2-dev1114.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/duckdb/extension/icu/icu-dateadd.cpp +30 -16
- package/src/duckdb/extension/icu/icu-datefunc.cpp +0 -8
- package/src/duckdb/extension/icu/third_party/icu/i18n/calendar.cpp +1 -1
- package/src/duckdb/src/common/enums/expression_type.cpp +2 -0
- package/src/duckdb/src/function/scalar/list/list_lambdas.cpp +6 -1
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/enums/expression_type.hpp +3 -1
- package/src/duckdb/src/include/duckdb/planner/expression/bound_lambdaref_expression.hpp +54 -0
- package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +2 -3
- package/src/duckdb/src/include/duckdb/planner/table_binding.hpp +2 -0
- package/src/duckdb/src/planner/binder/expression/bind_columnref_expression.cpp +2 -1
- package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +23 -3
- package/src/duckdb/src/planner/binder/expression/bind_lambda.cpp +35 -19
- package/src/duckdb/src/planner/expression/bound_lambdaref_expression.cpp +71 -0
- package/src/duckdb/src/planner/expression_iterator.cpp +1 -0
- package/src/duckdb/src/planner/table_binding.cpp +14 -4
- package/src/duckdb/ub_src_planner_expression.cpp +2 -0
package/package.json
CHANGED
|
@@ -57,23 +57,37 @@ timestamp_t ICUCalendarAdd::Operation(timestamp_t timestamp, interval_t interval
|
|
|
57
57
|
const auto udate = UDate(millis);
|
|
58
58
|
calendar->setTime(udate, status);
|
|
59
59
|
|
|
60
|
-
// Add interval fields from lowest to highest
|
|
61
|
-
|
|
62
60
|
// Break units apart to avoid overflow
|
|
63
|
-
auto
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
61
|
+
auto interval_h = interval.micros / Interval::MICROS_PER_MSEC;
|
|
62
|
+
|
|
63
|
+
const auto interval_ms = interval_h % Interval::MSECS_PER_SEC;
|
|
64
|
+
interval_h /= Interval::MSECS_PER_SEC;
|
|
65
|
+
|
|
66
|
+
const auto interval_s = interval_h % Interval::SECS_PER_MINUTE;
|
|
67
|
+
interval_h /= Interval::SECS_PER_MINUTE;
|
|
68
|
+
|
|
69
|
+
const auto interval_m = interval_h % Interval::MINS_PER_HOUR;
|
|
70
|
+
interval_h /= Interval::MINS_PER_HOUR;
|
|
71
|
+
|
|
72
|
+
if (interval.months < 0 || interval.days < 0 || interval.micros < 0) {
|
|
73
|
+
// Add interval fields from lowest to highest (non-ragged to ragged)
|
|
74
|
+
calendar->add(UCAL_MILLISECOND, interval_ms, status);
|
|
75
|
+
calendar->add(UCAL_SECOND, interval_s, status);
|
|
76
|
+
calendar->add(UCAL_MINUTE, interval_m, status);
|
|
77
|
+
calendar->add(UCAL_HOUR, interval_h, status);
|
|
78
|
+
|
|
79
|
+
calendar->add(UCAL_DATE, interval.days, status);
|
|
80
|
+
calendar->add(UCAL_MONTH, interval.months, status);
|
|
81
|
+
} else {
|
|
82
|
+
// Add interval fields from highest to lowest (ragged to non-ragged)
|
|
83
|
+
calendar->add(UCAL_MONTH, interval.months, status);
|
|
84
|
+
calendar->add(UCAL_DATE, interval.days, status);
|
|
85
|
+
|
|
86
|
+
calendar->add(UCAL_HOUR, interval_h, status);
|
|
87
|
+
calendar->add(UCAL_MINUTE, interval_m, status);
|
|
88
|
+
calendar->add(UCAL_SECOND, interval_s, status);
|
|
89
|
+
calendar->add(UCAL_MILLISECOND, interval_ms, status);
|
|
90
|
+
}
|
|
77
91
|
|
|
78
92
|
return ICUDateFunc::GetTime(calendar, micros);
|
|
79
93
|
}
|
|
@@ -112,14 +112,6 @@ int32_t ICUDateFunc::ExtractField(icu::Calendar *calendar, UCalendarDateFields f
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
int64_t ICUDateFunc::SubtractField(icu::Calendar *calendar, UCalendarDateFields field, timestamp_t end_date) {
|
|
115
|
-
// ICU triggers the address sanitiser because it tries to left shift a negative value
|
|
116
|
-
// when start_date > end_date. To avoid this, we swap the values and negate the result.
|
|
117
|
-
const auto start_date = GetTimeUnsafe(calendar);
|
|
118
|
-
if (start_date > end_date) {
|
|
119
|
-
SetTime(calendar, end_date);
|
|
120
|
-
return -SubtractField(calendar, field, start_date);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
115
|
const int64_t millis = end_date.value / Interval::MICROS_PER_MSEC;
|
|
124
116
|
const auto when = UDate(millis);
|
|
125
117
|
UErrorCode status = U_ZERO_ERROR;
|
|
@@ -2350,7 +2350,7 @@ int32_t Calendar::fieldDifference(UDate targetMs, UCalendarDateFields field, UEr
|
|
|
2350
2350
|
break;
|
|
2351
2351
|
} else {
|
|
2352
2352
|
min = max;
|
|
2353
|
-
max
|
|
2353
|
+
max = ((uint32_t) max) << 1;
|
|
2354
2354
|
if (max == 0) {
|
|
2355
2355
|
// Field difference too large to fit into int32_t
|
|
2356
2356
|
#if defined (U_DEBUG_CAL)
|
|
@@ -133,6 +133,8 @@ string ExpressionTypeToString(ExpressionType type) {
|
|
|
133
133
|
return "COLLATE";
|
|
134
134
|
case ExpressionType::POSITIONAL_REFERENCE:
|
|
135
135
|
return "POSITIONAL_REFERENCE";
|
|
136
|
+
case ExpressionType::BOUND_LAMBDA_REF:
|
|
137
|
+
return "BOUND_LAMBDA_REF";
|
|
136
138
|
case ExpressionType::LAMBDA:
|
|
137
139
|
return "LAMBDA";
|
|
138
140
|
case ExpressionType::ARROW:
|
|
@@ -112,15 +112,19 @@ static void ExecuteExpression(vector<LogicalType> &types, vector<LogicalType> &r
|
|
|
112
112
|
|
|
113
113
|
// set the list child vector
|
|
114
114
|
Vector slice(child_vector, sel, elem_cnt);
|
|
115
|
+
Vector second_slice(child_vector, sel, elem_cnt);
|
|
115
116
|
slice.Flatten(elem_cnt);
|
|
117
|
+
second_slice.Flatten(elem_cnt);
|
|
118
|
+
|
|
116
119
|
input_chunk.data[0].Reference(slice);
|
|
120
|
+
input_chunk.data[1].Reference(second_slice);
|
|
117
121
|
|
|
118
122
|
// set the other vectors
|
|
119
123
|
vector<Vector> slices;
|
|
120
124
|
for (idx_t col_idx = 0; col_idx < args.ColumnCount() - 1; col_idx++) {
|
|
121
125
|
slices.emplace_back(Vector(args.data[col_idx + 1], sel_vectors[col_idx], elem_cnt));
|
|
122
126
|
slices[col_idx].Flatten(elem_cnt);
|
|
123
|
-
input_chunk.data[col_idx +
|
|
127
|
+
input_chunk.data[col_idx + 2].Reference(slices[col_idx]);
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
// execute the lambda expression
|
|
@@ -185,6 +189,7 @@ static void ListLambdaFunction(DataChunk &args, ExpressionState &state, Vector &
|
|
|
185
189
|
|
|
186
190
|
vector<LogicalType> types;
|
|
187
191
|
types.push_back(child_vector.GetType());
|
|
192
|
+
types.push_back(child_vector.GetType());
|
|
188
193
|
|
|
189
194
|
// skip the list column
|
|
190
195
|
for (idx_t i = 1; i < args.ColumnCount(); i++) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
|
2
|
-
#define DUCKDB_VERSION "0.6.2-
|
|
2
|
+
#define DUCKDB_VERSION "0.6.2-dev1114"
|
|
3
3
|
#endif
|
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
|
5
|
+
#define DUCKDB_SOURCE_ID "51945c68c0"
|
|
6
6
|
#endif
|
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
|
8
8
|
#include "duckdb/main/database.hpp"
|
|
@@ -143,7 +143,8 @@ enum class ExpressionType : uint8_t {
|
|
|
143
143
|
BOUND_UNNEST = 229,
|
|
144
144
|
COLLATE = 230,
|
|
145
145
|
LAMBDA = 231,
|
|
146
|
-
POSITIONAL_REFERENCE = 232
|
|
146
|
+
POSITIONAL_REFERENCE = 232,
|
|
147
|
+
BOUND_LAMBDA_REF = 233
|
|
147
148
|
};
|
|
148
149
|
|
|
149
150
|
//===--------------------------------------------------------------------===//
|
|
@@ -192,6 +193,7 @@ enum class ExpressionClass : uint8_t {
|
|
|
192
193
|
BOUND_BETWEEN = 39,
|
|
193
194
|
BOUND_UNNEST = 40,
|
|
194
195
|
BOUND_LAMBDA = 41,
|
|
196
|
+
BOUND_LAMBDA_REF = 42,
|
|
195
197
|
//===--------------------------------------------------------------------===//
|
|
196
198
|
// Miscellaneous
|
|
197
199
|
//===--------------------------------------------------------------------===//
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//===----------------------------------------------------------------------===//
|
|
2
|
+
// DuckDB
|
|
3
|
+
//
|
|
4
|
+
// duckdb/planner/expression/bound_lambdaref_expression.hpp
|
|
5
|
+
//
|
|
6
|
+
//
|
|
7
|
+
//===----------------------------------------------------------------------===//
|
|
8
|
+
|
|
9
|
+
#pragma once
|
|
10
|
+
|
|
11
|
+
#include "duckdb/planner/column_binding.hpp"
|
|
12
|
+
#include "duckdb/planner/expression.hpp"
|
|
13
|
+
|
|
14
|
+
namespace duckdb {
|
|
15
|
+
|
|
16
|
+
class FieldReader;
|
|
17
|
+
class FieldWriter;
|
|
18
|
+
|
|
19
|
+
//! A BoundLambdaRef expression represents a LambdaRef expression that was bound to an lambda parameter
|
|
20
|
+
//! in the lambda bindings vector. When capturing lambdas the BoundLambdaRef becomes a
|
|
21
|
+
//! BoundReferenceExpresssion, indexing the corresponding lambda parameter in the lambda bindings vector,
|
|
22
|
+
//! which refers to the physical chunk of the lambda parameter during execution.
|
|
23
|
+
class BoundLambdaRefExpression : public Expression {
|
|
24
|
+
public:
|
|
25
|
+
BoundLambdaRefExpression(LogicalType type, ColumnBinding binding, idx_t lambda_index, idx_t depth = 0);
|
|
26
|
+
BoundLambdaRefExpression(string alias, LogicalType type, ColumnBinding binding, idx_t lambda_index,
|
|
27
|
+
idx_t depth = 0);
|
|
28
|
+
//! Column index set by the binder, used to generate the final BoundExpression
|
|
29
|
+
ColumnBinding binding;
|
|
30
|
+
//! The index of the lambda parameter in the lambda bindings vector
|
|
31
|
+
idx_t lambda_index;
|
|
32
|
+
//! The subquery depth (i.e. depth 0 = current query, depth 1 = parent query, depth 2 = parent of parent, etc...).
|
|
33
|
+
//! This is only non-zero for correlated expressions inside subqueries.
|
|
34
|
+
idx_t depth;
|
|
35
|
+
|
|
36
|
+
public:
|
|
37
|
+
bool IsScalar() const override {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
bool IsFoldable() const override {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
string ToString() const override;
|
|
45
|
+
|
|
46
|
+
bool Equals(const BaseExpression *other) const override;
|
|
47
|
+
hash_t Hash() const override;
|
|
48
|
+
|
|
49
|
+
unique_ptr<Expression> Copy() override;
|
|
50
|
+
|
|
51
|
+
void Serialize(FieldWriter &writer) const override;
|
|
52
|
+
static unique_ptr<Expression> Deserialize(ExpressionDeserializationState &state, FieldReader &reader);
|
|
53
|
+
};
|
|
54
|
+
} // namespace duckdb
|
|
@@ -126,10 +126,9 @@ protected:
|
|
|
126
126
|
BindResult BindExpression(SubqueryExpression &expr, idx_t depth);
|
|
127
127
|
|
|
128
128
|
void TransformCapturedLambdaColumn(unique_ptr<Expression> &original, unique_ptr<Expression> &replacement,
|
|
129
|
-
vector<unique_ptr<Expression>> &captures, LogicalType &list_child_type
|
|
130
|
-
string &alias);
|
|
129
|
+
vector<unique_ptr<Expression>> &captures, LogicalType &list_child_type);
|
|
131
130
|
void CaptureLambdaColumns(vector<unique_ptr<Expression>> &captures, LogicalType &list_child_type,
|
|
132
|
-
unique_ptr<Expression> &expr
|
|
131
|
+
unique_ptr<Expression> &expr);
|
|
133
132
|
|
|
134
133
|
protected:
|
|
135
134
|
virtual BindResult BindGroupingFunction(OperatorExpression &op, idx_t depth);
|
|
@@ -40,6 +40,7 @@ struct Binding {
|
|
|
40
40
|
string alias;
|
|
41
41
|
//! The table index of the binding
|
|
42
42
|
idx_t index;
|
|
43
|
+
//! The types of the bound columns
|
|
43
44
|
vector<LogicalType> types;
|
|
44
45
|
//! Column names of the subquery
|
|
45
46
|
vector<string> names;
|
|
@@ -99,6 +100,7 @@ public:
|
|
|
99
100
|
|
|
100
101
|
public:
|
|
101
102
|
BindResult Bind(ColumnRefExpression &colref, idx_t depth) override;
|
|
103
|
+
BindResult Bind(ColumnRefExpression &colref, idx_t lambda_index, idx_t depth);
|
|
102
104
|
|
|
103
105
|
//! Given the parameter colref, returns a copy of the argument that was supplied for this parameter
|
|
104
106
|
unique_ptr<ParsedExpression> ParamToArg(ColumnRefExpression &colref);
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "duckdb/parser/parsed_expression_iterator.hpp"
|
|
11
11
|
#include "duckdb/planner/binder.hpp"
|
|
12
12
|
#include "duckdb/planner/expression/bound_columnref_expression.hpp"
|
|
13
|
+
#include "duckdb/planner/expression/bound_lambdaref_expression.hpp"
|
|
13
14
|
#include "duckdb/planner/expression/bound_constant_expression.hpp"
|
|
14
15
|
#include "duckdb/planner/expression_binder.hpp"
|
|
15
16
|
#include "duckdb/planner/expression_binder/where_binder.hpp"
|
|
@@ -317,7 +318,7 @@ BindResult ExpressionBinder::BindExpression(ColumnRefExpression &colref_p, idx_t
|
|
|
317
318
|
if (lambda_bindings) {
|
|
318
319
|
for (idx_t i = 0; i < lambda_bindings->size(); i++) {
|
|
319
320
|
if (table_name == (*lambda_bindings)[i].alias) {
|
|
320
|
-
result = (*lambda_bindings)[i].Bind(colref, depth);
|
|
321
|
+
result = (*lambda_bindings)[i].Bind(colref, i, depth);
|
|
321
322
|
found_lambda_binding = true;
|
|
322
323
|
break;
|
|
323
324
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include "duckdb/planner/expression/bound_cast_expression.hpp"
|
|
6
6
|
#include "duckdb/planner/expression/bound_constant_expression.hpp"
|
|
7
7
|
#include "duckdb/planner/expression/bound_function_expression.hpp"
|
|
8
|
+
#include "duckdb/planner/expression/bound_reference_expression.hpp"
|
|
8
9
|
#include "duckdb/planner/expression/bound_lambda_expression.hpp"
|
|
9
10
|
#include "duckdb/planner/expression_binder.hpp"
|
|
10
11
|
#include "duckdb/planner/binder.hpp"
|
|
@@ -155,8 +156,7 @@ BindResult ExpressionBinder::BindLambdaFunction(FunctionExpression &function, Sc
|
|
|
155
156
|
|
|
156
157
|
// capture the (lambda) columns
|
|
157
158
|
auto &bound_lambda_expr = (BoundLambdaExpression &)*children.back();
|
|
158
|
-
CaptureLambdaColumns(bound_lambda_expr.captures, list_child_type, bound_lambda_expr.lambda_expr
|
|
159
|
-
children[0]->alias);
|
|
159
|
+
CaptureLambdaColumns(bound_lambda_expr.captures, list_child_type, bound_lambda_expr.lambda_expr);
|
|
160
160
|
|
|
161
161
|
FunctionBinder function_binder(context);
|
|
162
162
|
unique_ptr<Expression> result =
|
|
@@ -165,12 +165,32 @@ BindResult ExpressionBinder::BindLambdaFunction(FunctionExpression &function, Sc
|
|
|
165
165
|
throw BinderException(binder.FormatError(function, error));
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
// remove the lambda expression from the children
|
|
169
168
|
auto &bound_function_expr = (BoundFunctionExpression &)*result;
|
|
169
|
+
D_ASSERT(bound_function_expr.children.size() == 2);
|
|
170
|
+
|
|
171
|
+
// remove the lambda expression from the children
|
|
170
172
|
auto lambda = std::move(bound_function_expr.children.back());
|
|
171
173
|
bound_function_expr.children.pop_back();
|
|
172
174
|
auto &bound_lambda = (BoundLambdaExpression &)*lambda;
|
|
173
175
|
|
|
176
|
+
// push back (in reverse order) any nested lambda parameters so that we can later use them in the lambda expression
|
|
177
|
+
// (rhs)
|
|
178
|
+
if (lambda_bindings) {
|
|
179
|
+
for (idx_t i = lambda_bindings->size(); i > 0; i--) {
|
|
180
|
+
|
|
181
|
+
idx_t lambda_index = lambda_bindings->size() - i + 1;
|
|
182
|
+
auto &binding = (*lambda_bindings)[i - 1];
|
|
183
|
+
|
|
184
|
+
D_ASSERT(binding.names.size() == 1);
|
|
185
|
+
D_ASSERT(binding.types.size() == 1);
|
|
186
|
+
|
|
187
|
+
bound_function_expr.function.arguments.push_back(binding.types[0]);
|
|
188
|
+
auto bound_lambda_param =
|
|
189
|
+
make_unique<BoundReferenceExpression>(binding.names[0], binding.types[0], lambda_index);
|
|
190
|
+
bound_function_expr.children.push_back(std::move(bound_lambda_param));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
174
194
|
// push back the captures into the children vector and the correct return types into the bound_function arguments
|
|
175
195
|
for (auto &capture : bound_lambda.captures) {
|
|
176
196
|
bound_function_expr.function.arguments.push_back(capture->return_type);
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include "duckdb/planner/binder.hpp"
|
|
7
7
|
#include "duckdb/parser/expression/function_expression.hpp"
|
|
8
8
|
#include "duckdb/planner/expression/bound_reference_expression.hpp"
|
|
9
|
+
#include "duckdb/planner/expression/bound_lambdaref_expression.hpp"
|
|
9
10
|
#include "duckdb/planner/expression/bound_lambda_expression.hpp"
|
|
10
11
|
#include "duckdb/planner/expression_iterator.hpp"
|
|
11
12
|
|
|
@@ -102,33 +103,48 @@ BindResult ExpressionBinder::BindExpression(LambdaExpression &expr, idx_t depth,
|
|
|
102
103
|
void ExpressionBinder::TransformCapturedLambdaColumn(unique_ptr<Expression> &original,
|
|
103
104
|
unique_ptr<Expression> &replacement,
|
|
104
105
|
vector<unique_ptr<Expression>> &captures,
|
|
105
|
-
LogicalType &list_child_type
|
|
106
|
+
LogicalType &list_child_type) {
|
|
106
107
|
|
|
107
108
|
// check if the original expression is a lambda parameter
|
|
108
|
-
|
|
109
|
-
if (original->expression_class == ExpressionClass::BOUND_COLUMN_REF) {
|
|
109
|
+
if (original->expression_class == ExpressionClass::BOUND_LAMBDA_REF) {
|
|
110
110
|
|
|
111
111
|
// determine if this is the lambda parameter
|
|
112
|
-
auto &
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
auto &bound_lambda_ref = (BoundLambdaRefExpression &)*original;
|
|
113
|
+
auto alias = bound_lambda_ref.alias;
|
|
114
|
+
|
|
115
|
+
if (lambda_bindings && bound_lambda_ref.lambda_index != lambda_bindings->size()) {
|
|
116
|
+
|
|
117
|
+
D_ASSERT(bound_lambda_ref.lambda_index < lambda_bindings->size());
|
|
118
|
+
auto &lambda_binding = (*lambda_bindings)[bound_lambda_ref.lambda_index];
|
|
117
119
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
D_ASSERT(lambda_binding.names.size() == 1);
|
|
121
|
+
D_ASSERT(lambda_binding.types.size() == 1);
|
|
122
|
+
// refers to a lambda parameter outside of the current lambda function
|
|
123
|
+
replacement =
|
|
124
|
+
make_unique<BoundReferenceExpression>(lambda_binding.names[0], lambda_binding.types[0],
|
|
125
|
+
lambda_bindings->size() - bound_lambda_ref.lambda_index + 1);
|
|
126
|
+
|
|
127
|
+
} else {
|
|
128
|
+
// refers to current lambda parameter
|
|
129
|
+
replacement = make_unique<BoundReferenceExpression>(alias, list_child_type, 0);
|
|
130
|
+
}
|
|
121
131
|
|
|
122
132
|
} else {
|
|
133
|
+
// always at least the current lambda parameter
|
|
134
|
+
idx_t index_offset = 1;
|
|
135
|
+
if (lambda_bindings) {
|
|
136
|
+
index_offset += lambda_bindings->size();
|
|
137
|
+
}
|
|
138
|
+
|
|
123
139
|
// this is not a lambda parameter, so we need to create a new argument for the arguments vector
|
|
124
|
-
replacement =
|
|
125
|
-
|
|
140
|
+
replacement = make_unique<BoundReferenceExpression>(original->alias, original->return_type,
|
|
141
|
+
captures.size() + index_offset + 1);
|
|
126
142
|
captures.push_back(std::move(original));
|
|
127
143
|
}
|
|
128
144
|
}
|
|
129
145
|
|
|
130
146
|
void ExpressionBinder::CaptureLambdaColumns(vector<unique_ptr<Expression>> &captures, LogicalType &list_child_type,
|
|
131
|
-
unique_ptr<Expression> &expr
|
|
147
|
+
unique_ptr<Expression> &expr) {
|
|
132
148
|
|
|
133
149
|
if (expr->expression_class == ExpressionClass::BOUND_SUBQUERY) {
|
|
134
150
|
throw InvalidInputException("Subqueries are not supported in lambda expressions!");
|
|
@@ -137,22 +153,22 @@ void ExpressionBinder::CaptureLambdaColumns(vector<unique_ptr<Expression>> &capt
|
|
|
137
153
|
// these expression classes do not have children, transform them
|
|
138
154
|
if (expr->expression_class == ExpressionClass::BOUND_CONSTANT ||
|
|
139
155
|
expr->expression_class == ExpressionClass::BOUND_COLUMN_REF ||
|
|
140
|
-
expr->expression_class == ExpressionClass::BOUND_PARAMETER
|
|
156
|
+
expr->expression_class == ExpressionClass::BOUND_PARAMETER ||
|
|
157
|
+
expr->expression_class == ExpressionClass::BOUND_LAMBDA_REF) {
|
|
141
158
|
|
|
142
159
|
// move the expr because we are going to replace it
|
|
143
160
|
auto original = std::move(expr);
|
|
144
161
|
unique_ptr<Expression> replacement;
|
|
145
162
|
|
|
146
|
-
TransformCapturedLambdaColumn(original, replacement, captures, list_child_type
|
|
163
|
+
TransformCapturedLambdaColumn(original, replacement, captures, list_child_type);
|
|
147
164
|
|
|
148
165
|
// replace the expression
|
|
149
166
|
expr = std::move(replacement);
|
|
150
167
|
|
|
151
168
|
} else {
|
|
152
169
|
// recursively enumerate the children of the expression
|
|
153
|
-
ExpressionIterator::EnumerateChildren(
|
|
154
|
-
|
|
155
|
-
});
|
|
170
|
+
ExpressionIterator::EnumerateChildren(
|
|
171
|
+
*expr, [&](unique_ptr<Expression> &child) { CaptureLambdaColumns(captures, list_child_type, child); });
|
|
156
172
|
}
|
|
157
173
|
}
|
|
158
174
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#include "duckdb/planner/expression/bound_lambdaref_expression.hpp"
|
|
2
|
+
|
|
3
|
+
#include "duckdb/common/types/hash.hpp"
|
|
4
|
+
#include "duckdb/common/to_string.hpp"
|
|
5
|
+
#include "duckdb/common/field_writer.hpp"
|
|
6
|
+
|
|
7
|
+
namespace duckdb {
|
|
8
|
+
|
|
9
|
+
BoundLambdaRefExpression::BoundLambdaRefExpression(string alias_p, LogicalType type, ColumnBinding binding,
|
|
10
|
+
idx_t lambda_index, idx_t depth)
|
|
11
|
+
: Expression(ExpressionType::BOUND_LAMBDA_REF, ExpressionClass::BOUND_LAMBDA_REF, move(type)), binding(binding),
|
|
12
|
+
lambda_index(lambda_index), depth(depth) {
|
|
13
|
+
this->alias = move(alias_p);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
BoundLambdaRefExpression::BoundLambdaRefExpression(LogicalType type, ColumnBinding binding, idx_t lambda_index,
|
|
17
|
+
idx_t depth)
|
|
18
|
+
: BoundLambdaRefExpression(string(), move(type), binding, lambda_index, depth) {
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
unique_ptr<Expression> BoundLambdaRefExpression::Copy() {
|
|
22
|
+
return make_unique<BoundLambdaRefExpression>(alias, return_type, binding, lambda_index, depth);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
hash_t BoundLambdaRefExpression::Hash() const {
|
|
26
|
+
auto result = Expression::Hash();
|
|
27
|
+
result = CombineHash(result, duckdb::Hash<uint64_t>(lambda_index));
|
|
28
|
+
result = CombineHash(result, duckdb::Hash<uint64_t>(binding.column_index));
|
|
29
|
+
result = CombineHash(result, duckdb::Hash<uint64_t>(binding.table_index));
|
|
30
|
+
return CombineHash(result, duckdb::Hash<uint64_t>(depth));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
bool BoundLambdaRefExpression::Equals(const BaseExpression *other_p) const {
|
|
34
|
+
if (!Expression::Equals(other_p)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
auto other = (BoundLambdaRefExpression *)other_p;
|
|
38
|
+
return other->binding == binding && other->lambda_index == lambda_index && other->depth == depth;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
string BoundLambdaRefExpression::ToString() const {
|
|
42
|
+
if (!alias.empty()) {
|
|
43
|
+
return alias;
|
|
44
|
+
}
|
|
45
|
+
return "#[" + to_string(binding.table_index) + "." + to_string(binding.column_index) + "." +
|
|
46
|
+
to_string(lambda_index) + "]";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void BoundLambdaRefExpression::Serialize(FieldWriter &writer) const {
|
|
50
|
+
writer.WriteString(alias);
|
|
51
|
+
writer.WriteSerializable(return_type);
|
|
52
|
+
writer.WriteField(lambda_index);
|
|
53
|
+
writer.WriteField(binding.table_index);
|
|
54
|
+
writer.WriteField(binding.column_index);
|
|
55
|
+
writer.WriteField(depth);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
unique_ptr<Expression> BoundLambdaRefExpression::Deserialize(ExpressionDeserializationState &state,
|
|
59
|
+
FieldReader &reader) {
|
|
60
|
+
auto alias = reader.ReadRequired<string>();
|
|
61
|
+
auto return_type = reader.ReadRequiredSerializable<LogicalType, LogicalType>();
|
|
62
|
+
auto lambda_index = reader.ReadRequired<idx_t>();
|
|
63
|
+
auto table_index = reader.ReadRequired<idx_t>();
|
|
64
|
+
auto column_index = reader.ReadRequired<idx_t>();
|
|
65
|
+
auto depth = reader.ReadRequired<idx_t>();
|
|
66
|
+
|
|
67
|
+
return make_unique<BoundLambdaRefExpression>(alias, return_type, ColumnBinding(table_index, column_index),
|
|
68
|
+
lambda_index, depth);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
} // namespace duckdb
|
|
@@ -120,6 +120,7 @@ void ExpressionIterator::EnumerateChildren(Expression &expr,
|
|
|
120
120
|
break;
|
|
121
121
|
}
|
|
122
122
|
case ExpressionClass::BOUND_COLUMN_REF:
|
|
123
|
+
case ExpressionClass::BOUND_LAMBDA_REF:
|
|
123
124
|
case ExpressionClass::BOUND_CONSTANT:
|
|
124
125
|
case ExpressionClass::BOUND_DEFAULT:
|
|
125
126
|
case ExpressionClass::BOUND_PARAMETER:
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include "duckdb/planner/bind_context.hpp"
|
|
9
9
|
#include "duckdb/planner/bound_query_node.hpp"
|
|
10
10
|
#include "duckdb/planner/expression/bound_columnref_expression.hpp"
|
|
11
|
+
#include "duckdb/planner/expression/bound_lambdaref_expression.hpp"
|
|
11
12
|
#include "duckdb/parser/parsed_expression_iterator.hpp"
|
|
12
13
|
|
|
13
14
|
namespace duckdb {
|
|
@@ -200,7 +201,8 @@ string TableBinding::ColumnNotFoundError(const string &column_name) const {
|
|
|
200
201
|
}
|
|
201
202
|
|
|
202
203
|
DummyBinding::DummyBinding(vector<LogicalType> types_p, vector<string> names_p, string dummy_name_p)
|
|
203
|
-
: Binding(BindingType::DUMMY, DummyBinding::DUMMY_NAME + dummy_name_p, std::move(types_p), std::move(names_p),
|
|
204
|
+
: Binding(BindingType::DUMMY, DummyBinding::DUMMY_NAME + dummy_name_p, std::move(types_p), std::move(names_p),
|
|
205
|
+
DConstants::INVALID_INDEX),
|
|
204
206
|
dummy_name(std::move(dummy_name_p)) {
|
|
205
207
|
}
|
|
206
208
|
|
|
@@ -209,14 +211,22 @@ BindResult DummyBinding::Bind(ColumnRefExpression &colref, idx_t depth) {
|
|
|
209
211
|
if (!TryGetBindingIndex(colref.GetColumnName(), column_index)) {
|
|
210
212
|
throw InternalException("Column %s not found in bindings", colref.GetColumnName());
|
|
211
213
|
}
|
|
212
|
-
ColumnBinding binding;
|
|
213
|
-
binding.table_index = index;
|
|
214
|
-
binding.column_index = column_index;
|
|
214
|
+
ColumnBinding binding(index, column_index);
|
|
215
215
|
|
|
216
216
|
// we are binding a parameter to create the dummy binding, no arguments are supplied
|
|
217
217
|
return BindResult(make_unique<BoundColumnRefExpression>(colref.GetName(), types[column_index], binding, depth));
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
BindResult DummyBinding::Bind(ColumnRefExpression &colref, idx_t lambda_index, idx_t depth) {
|
|
221
|
+
column_t column_index;
|
|
222
|
+
if (!TryGetBindingIndex(colref.GetColumnName(), column_index)) {
|
|
223
|
+
throw InternalException("Column %s not found in bindings", colref.GetColumnName());
|
|
224
|
+
}
|
|
225
|
+
ColumnBinding binding(index, column_index);
|
|
226
|
+
return BindResult(
|
|
227
|
+
make_unique<BoundLambdaRefExpression>(colref.GetName(), types[column_index], binding, lambda_index, depth));
|
|
228
|
+
}
|
|
229
|
+
|
|
220
230
|
unique_ptr<ParsedExpression> DummyBinding::ParamToArg(ColumnRefExpression &colref) {
|
|
221
231
|
column_t column_index;
|
|
222
232
|
if (!TryGetBindingIndex(colref.GetColumnName(), column_index)) {
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
|
|
23
23
|
#include "src/planner/expression/bound_lambda_expression.cpp"
|
|
24
24
|
|
|
25
|
+
#include "src/planner/expression/bound_lambdaref_expression.cpp"
|
|
26
|
+
|
|
25
27
|
#include "src/planner/expression/bound_operator_expression.cpp"
|
|
26
28
|
|
|
27
29
|
#include "src/planner/expression/bound_parameter_expression.cpp"
|