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 CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
4
  "types": "./lib/duckdb.d.ts",
5
- "version": "0.6.2-dev1097.0",
5
+ "version": "0.6.2-dev1114.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -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 remaining = interval.micros / Interval::MICROS_PER_MSEC;
64
- calendar->add(UCAL_MILLISECOND, remaining % Interval::MSECS_PER_SEC, status);
65
-
66
- remaining /= Interval::MSECS_PER_SEC;
67
- calendar->add(UCAL_SECOND, remaining % Interval::SECS_PER_MINUTE, status);
68
-
69
- remaining /= Interval::SECS_PER_MINUTE;
70
- calendar->add(UCAL_MINUTE, remaining % Interval::MINS_PER_HOUR, status);
71
-
72
- remaining /= Interval::MINS_PER_HOUR;
73
- calendar->add(UCAL_HOUR, remaining, status);
74
-
75
- calendar->add(UCAL_DATE, interval.days, status);
76
- calendar->add(UCAL_MONTH, interval.months, status);
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 <<= 1;
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 + 1].Reference(slices[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-dev1097"
2
+ #define DUCKDB_VERSION "0.6.2-dev1114"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "9e64704159"
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, string &alias);
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, string &alias) {
106
+ LogicalType &list_child_type) {
106
107
 
107
108
  // check if the original expression is a lambda parameter
108
- bool is_lambda_parameter = false;
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 &bound_col_ref = (BoundColumnRefExpression &)*original;
113
- if (bound_col_ref.binding.table_index == DConstants::INVALID_INDEX) {
114
- is_lambda_parameter = true;
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
- if (is_lambda_parameter) {
119
- // this is a lambda parameter, so the replacement refers to the first argument, which is the list
120
- replacement = make_unique<BoundReferenceExpression>(alias, list_child_type, 0);
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
- make_unique<BoundReferenceExpression>(original->alias, original->return_type, captures.size() + 1);
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, string &alias) {
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, alias);
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(*expr, [&](unique_ptr<Expression> &child) {
154
- CaptureLambdaColumns(captures, list_child_type, child, alias);
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), -1),
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"