duckdb 0.3.3-dev1232.0 → 0.3.3-dev1251.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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
- "version": "0.3.3-dev1232.0",
4
+ "version": "0.3.3-dev1251.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -64051,14 +64051,15 @@ class DataTable;
64051
64051
  class PhysicalDelete : public PhysicalOperator {
64052
64052
  public:
64053
64053
  PhysicalDelete(vector<LogicalType> types, TableCatalogEntry &tableref, DataTable &table, idx_t row_id_index,
64054
- idx_t estimated_cardinality)
64054
+ idx_t estimated_cardinality, bool return_chunk)
64055
64055
  : PhysicalOperator(PhysicalOperatorType::DELETE_OPERATOR, move(types), estimated_cardinality),
64056
- tableref(tableref), table(table), row_id_index(row_id_index) {
64056
+ tableref(tableref), table(table), row_id_index(row_id_index), return_chunk(return_chunk) {
64057
64057
  }
64058
64058
 
64059
64059
  TableCatalogEntry &tableref;
64060
64060
  DataTable &table;
64061
64061
  idx_t row_id_index;
64062
+ bool return_chunk;
64062
64063
 
64063
64064
  public:
64064
64065
  // Source interface
@@ -64069,6 +64070,7 @@ public:
64069
64070
  public:
64070
64071
  // Sink interface
64071
64072
  unique_ptr<GlobalSinkState> GetGlobalSinkState(ClientContext &context) const override;
64073
+ unique_ptr<LocalSinkState> GetLocalSinkState(ExecutionContext &context) const override;
64072
64074
  SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate,
64073
64075
  DataChunk &input) const override;
64074
64076
 
@@ -64088,6 +64090,7 @@ public:
64088
64090
 
64089
64091
 
64090
64092
 
64093
+
64091
64094
  namespace duckdb {
64092
64095
 
64093
64096
  //===--------------------------------------------------------------------===//
@@ -64095,21 +64098,46 @@ namespace duckdb {
64095
64098
  //===--------------------------------------------------------------------===//
64096
64099
  class DeleteGlobalState : public GlobalSinkState {
64097
64100
  public:
64098
- DeleteGlobalState() : deleted_count(0) {
64101
+ DeleteGlobalState() : deleted_count(0), returned_chunk_count(0) {
64099
64102
  }
64100
64103
 
64101
64104
  mutex delete_lock;
64102
64105
  idx_t deleted_count;
64106
+ ChunkCollection return_chunk_collection;
64107
+ idx_t returned_chunk_count;
64108
+ };
64109
+
64110
+ class DeleteLocalState : public LocalSinkState {
64111
+ public:
64112
+ explicit DeleteLocalState(const vector<LogicalType> &table_types) {
64113
+ delete_chunk.Initialize(table_types);
64114
+ }
64115
+ DataChunk delete_chunk;
64103
64116
  };
64104
64117
 
64105
64118
  SinkResultType PhysicalDelete::Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate,
64106
64119
  DataChunk &input) const {
64107
64120
  auto &gstate = (DeleteGlobalState &)state;
64121
+ auto &ustate = (DeleteLocalState &)lstate;
64122
+
64123
+ // get rows and
64124
+ auto &transaction = Transaction::GetTransaction(context.client);
64125
+ auto &row_identifiers = input.data[row_id_index];
64126
+
64127
+ vector<column_t> column_ids;
64128
+ for (idx_t i = 0; i < table.column_definitions.size(); i++) {
64129
+ column_ids.emplace_back(i);
64130
+ };
64131
+ auto cfs = ColumnFetchState();
64108
64132
 
64109
- // delete data in the base table
64110
- // the row ids are given to us as the last column of the child chunk
64111
64133
  lock_guard<mutex> delete_guard(gstate.delete_lock);
64112
- gstate.deleted_count += table.Delete(tableref, context.client, input.data[row_id_index], input.size());
64134
+ if (return_chunk) {
64135
+ row_identifiers.Normalify(input.size());
64136
+ table.Fetch(transaction, ustate.delete_chunk, column_ids, row_identifiers, input.size(), cfs);
64137
+ gstate.return_chunk_collection.Append(ustate.delete_chunk);
64138
+ }
64139
+ gstate.deleted_count += table.Delete(tableref, context.client, row_identifiers, input.size());
64140
+
64113
64141
  return SinkResultType::NEED_MORE_INPUT;
64114
64142
  }
64115
64143
 
@@ -64117,6 +64145,10 @@ unique_ptr<GlobalSinkState> PhysicalDelete::GetGlobalSinkState(ClientContext &co
64117
64145
  return make_unique<DeleteGlobalState>();
64118
64146
  }
64119
64147
 
64148
+ unique_ptr<LocalSinkState> PhysicalDelete::GetLocalSinkState(ExecutionContext &context) const {
64149
+ return make_unique<DeleteLocalState>(table.GetTypes());
64150
+ }
64151
+
64120
64152
  //===--------------------------------------------------------------------===//
64121
64153
  // Source
64122
64154
  //===--------------------------------------------------------------------===//
@@ -64140,9 +64172,22 @@ void PhysicalDelete::GetData(ExecutionContext &context, DataChunk &chunk, Global
64140
64172
  return;
64141
64173
  }
64142
64174
 
64143
- chunk.SetCardinality(1);
64144
- chunk.SetValue(0, 0, Value::BIGINT(g.deleted_count));
64145
- state.finished = true;
64175
+ if (!return_chunk) {
64176
+ chunk.SetCardinality(1);
64177
+ chunk.SetValue(0, 0, Value::BIGINT(g.deleted_count));
64178
+ state.finished = true;
64179
+ }
64180
+
64181
+ idx_t chunk_return = g.returned_chunk_count;
64182
+ if (chunk_return >= g.return_chunk_collection.Chunks().size()) {
64183
+ return;
64184
+ }
64185
+ chunk.Reference(g.return_chunk_collection.GetChunk(chunk_return));
64186
+ chunk.SetCardinality((g.return_chunk_collection.GetChunk(chunk_return)).size());
64187
+ g.returned_chunk_count += 1;
64188
+ if (g.returned_chunk_count >= g.return_chunk_collection.Chunks().size()) {
64189
+ state.finished = true;
64190
+ }
64146
64191
  }
64147
64192
 
64148
64193
  } // namespace duckdb
@@ -64589,10 +64634,10 @@ class PhysicalUpdate : public PhysicalOperator {
64589
64634
  public:
64590
64635
  PhysicalUpdate(vector<LogicalType> types, TableCatalogEntry &tableref, DataTable &table, vector<column_t> columns,
64591
64636
  vector<unique_ptr<Expression>> expressions, vector<unique_ptr<Expression>> bound_defaults,
64592
- idx_t estimated_cardinality)
64637
+ idx_t estimated_cardinality, bool return_chunk)
64593
64638
  : PhysicalOperator(PhysicalOperatorType::UPDATE, move(types), estimated_cardinality), tableref(tableref),
64594
64639
  table(table), columns(std::move(columns)), expressions(move(expressions)),
64595
- bound_defaults(move(bound_defaults)) {
64640
+ bound_defaults(move(bound_defaults)), return_chunk(return_chunk) {
64596
64641
  }
64597
64642
 
64598
64643
  TableCatalogEntry &tableref;
@@ -64601,6 +64646,8 @@ public:
64601
64646
  vector<unique_ptr<Expression>> expressions;
64602
64647
  vector<unique_ptr<Expression>> bound_defaults;
64603
64648
  bool update_is_del_and_insert;
64649
+ //! If the returning statement is present, return the whole chunk
64650
+ bool return_chunk;
64604
64651
 
64605
64652
  public:
64606
64653
  // Source interface
@@ -64634,6 +64681,7 @@ public:
64634
64681
 
64635
64682
 
64636
64683
 
64684
+
64637
64685
  namespace duckdb {
64638
64686
 
64639
64687
  //===--------------------------------------------------------------------===//
@@ -64641,12 +64689,14 @@ namespace duckdb {
64641
64689
  //===--------------------------------------------------------------------===//
64642
64690
  class UpdateGlobalState : public GlobalSinkState {
64643
64691
  public:
64644
- UpdateGlobalState() : updated_count(0) {
64692
+ UpdateGlobalState() : updated_count(0), returned_chunk_count(0) {
64645
64693
  }
64646
64694
 
64647
64695
  mutex lock;
64648
64696
  idx_t updated_count;
64649
64697
  unordered_set<row_t> updated_columns;
64698
+ ChunkCollection return_chunk_collection;
64699
+ idx_t returned_chunk_count;
64650
64700
  };
64651
64701
 
64652
64702
  class UpdateLocalState : public LocalSinkState {
@@ -64726,9 +64776,21 @@ SinkResultType PhysicalUpdate::Sink(ExecutionContext &context, GlobalSinkState &
64726
64776
  }
64727
64777
  table.Append(tableref, context.client, mock_chunk);
64728
64778
  } else {
64779
+ if (return_chunk) {
64780
+ mock_chunk.SetCardinality(update_chunk);
64781
+ for (idx_t i = 0; i < columns.size(); i++) {
64782
+ mock_chunk.data[columns[i]].Reference(update_chunk.data[i]);
64783
+ }
64784
+ }
64729
64785
  table.Update(tableref, context.client, row_ids, columns, update_chunk);
64730
64786
  }
64787
+
64788
+ if (return_chunk) {
64789
+ gstate.return_chunk_collection.Append(mock_chunk);
64790
+ }
64791
+
64731
64792
  gstate.updated_count += chunk.size();
64793
+
64732
64794
  return SinkResultType::NEED_MORE_INPUT;
64733
64795
  }
64734
64796
 
@@ -64769,10 +64831,22 @@ void PhysicalUpdate::GetData(ExecutionContext &context, DataChunk &chunk, Global
64769
64831
  if (state.finished) {
64770
64832
  return;
64771
64833
  }
64834
+ if (!return_chunk) {
64835
+ chunk.SetCardinality(1);
64836
+ chunk.SetValue(0, 0, Value::BIGINT(g.updated_count));
64837
+ state.finished = true;
64838
+ }
64772
64839
 
64773
- chunk.SetCardinality(1);
64774
- chunk.SetValue(0, 0, Value::BIGINT(g.updated_count));
64775
- state.finished = true;
64840
+ idx_t chunk_return = g.returned_chunk_count;
64841
+ if (chunk_return >= g.return_chunk_collection.Chunks().size()) {
64842
+ return;
64843
+ }
64844
+ chunk.Reference(g.return_chunk_collection.GetChunk(chunk_return));
64845
+ chunk.SetCardinality((g.return_chunk_collection.GetChunk(chunk_return)).size());
64846
+ g.returned_chunk_count += 1;
64847
+ if (g.returned_chunk_count >= g.return_chunk_collection.Chunks().size()) {
64848
+ state.finished = true;
64849
+ }
64776
64850
  }
64777
64851
 
64778
64852
  } // namespace duckdb
@@ -68395,14 +68469,27 @@ namespace duckdb {
68395
68469
  class LogicalDelete : public LogicalOperator {
68396
68470
  public:
68397
68471
  explicit LogicalDelete(TableCatalogEntry *table)
68398
- : LogicalOperator(LogicalOperatorType::LOGICAL_DELETE), table(table) {
68472
+ : LogicalOperator(LogicalOperatorType::LOGICAL_DELETE), table(table), table_index(0), return_chunk(false) {
68399
68473
  }
68400
68474
 
68401
68475
  TableCatalogEntry *table;
68476
+ idx_t table_index;
68477
+ bool return_chunk;
68402
68478
 
68403
68479
  protected:
68480
+ vector<ColumnBinding> GetColumnBindings() override {
68481
+ if (return_chunk) {
68482
+ return GenerateColumnBindings(table_index, table->columns.size());
68483
+ }
68484
+ return {ColumnBinding(0, 0)};
68485
+ }
68486
+
68404
68487
  void ResolveTypes() override {
68405
- types.emplace_back(LogicalType::BIGINT);
68488
+ if (return_chunk) {
68489
+ types = table->GetTypes();
68490
+ } else {
68491
+ types.emplace_back(LogicalType::BIGINT);
68492
+ }
68406
68493
  }
68407
68494
  };
68408
68495
  } // namespace duckdb
@@ -68421,8 +68508,8 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalDelete &op
68421
68508
  auto &bound_ref = (BoundReferenceExpression &)*op.expressions[0];
68422
68509
 
68423
68510
  dependencies.insert(op.table);
68424
- auto del =
68425
- make_unique<PhysicalDelete>(op.types, *op.table, *op.table->storage, bound_ref.index, op.estimated_cardinality);
68511
+ auto del = make_unique<PhysicalDelete>(op.types, *op.table, *op.table->storage, bound_ref.index,
68512
+ op.estimated_cardinality, op.return_chunk);
68426
68513
  del->children.push_back(move(plan));
68427
68514
  return move(del);
68428
68515
  }
@@ -70711,17 +70798,33 @@ namespace duckdb {
70711
70798
  class LogicalUpdate : public LogicalOperator {
70712
70799
  public:
70713
70800
  explicit LogicalUpdate(TableCatalogEntry *table)
70714
- : LogicalOperator(LogicalOperatorType::LOGICAL_UPDATE), table(table) {
70801
+ : LogicalOperator(LogicalOperatorType::LOGICAL_UPDATE), table(table), table_index(0), return_chunk(false) {
70715
70802
  }
70716
70803
 
70804
+ //! The base table to update
70717
70805
  TableCatalogEntry *table;
70806
+ //! table catalog index
70807
+ idx_t table_index;
70808
+ //! if returning option is used, return the update chunk
70809
+ bool return_chunk;
70718
70810
  vector<column_t> columns;
70719
70811
  vector<unique_ptr<Expression>> bound_defaults;
70720
70812
  bool update_is_del_and_insert;
70721
70813
 
70722
70814
  protected:
70815
+ vector<ColumnBinding> GetColumnBindings() override {
70816
+ if (return_chunk) {
70817
+ return GenerateColumnBindings(table_index, table->columns.size());
70818
+ }
70819
+ return {ColumnBinding(0, 0)};
70820
+ }
70821
+
70723
70822
  void ResolveTypes() override {
70724
- types.emplace_back(LogicalType::BIGINT);
70823
+ if (return_chunk) {
70824
+ types = table->GetTypes();
70825
+ } else {
70826
+ types.emplace_back(LogicalType::BIGINT);
70827
+ }
70725
70828
  }
70726
70829
  };
70727
70830
  } // namespace duckdb
@@ -70736,7 +70839,8 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalUpdate &op
70736
70839
 
70737
70840
  dependencies.insert(op.table);
70738
70841
  auto update = make_unique<PhysicalUpdate>(op.types, *op.table, *op.table->storage, op.columns, move(op.expressions),
70739
- move(op.bound_defaults), op.estimated_cardinality);
70842
+ move(op.bound_defaults), op.estimated_cardinality, op.return_chunk);
70843
+
70740
70844
  update->update_is_del_and_insert = op.update_is_del_and_insert;
70741
70845
  update->children.push_back(move(plan));
70742
70846
  return move(update);
@@ -119089,6 +119193,7 @@ public:
119089
119193
  unique_ptr<ParsedExpression> condition;
119090
119194
  unique_ptr<TableRef> table;
119091
119195
  vector<unique_ptr<TableRef>> using_clauses;
119196
+ vector<unique_ptr<ParsedExpression>> returning_list;
119092
119197
 
119093
119198
  protected:
119094
119199
  DeleteStatement(const DeleteStatement &other);
@@ -120393,6 +120498,8 @@ public:
120393
120498
  unique_ptr<TableRef> from_table;
120394
120499
  vector<string> columns;
120395
120500
  vector<unique_ptr<ParsedExpression>> expressions;
120501
+ //! keep track of optional returningList if statement contains a RETURNING keyword
120502
+ vector<unique_ptr<ParsedExpression>> returning_list;
120396
120503
 
120397
120504
  protected:
120398
120505
  UpdateStatement(const UpdateStatement &other);
@@ -127788,10 +127895,14 @@ void RemoveUnusedColumns::VisitOperator(LogicalOperator &op) {
127788
127895
  remove.VisitOperator(*op.children[0]);
127789
127896
  return;
127790
127897
  }
127791
- case LogicalOperatorType::LOGICAL_INSERT: {
127792
- //! When RETURNING is used, a PROJECTION is the top level operator
127793
- //! We still need to project all values from the insert so the projection
127794
- //! on top of the INSERT can select from only that table values being inserted
127898
+ case LogicalOperatorType::LOGICAL_INSERT:
127899
+ case LogicalOperatorType::LOGICAL_UPDATE:
127900
+ case LogicalOperatorType::LOGICAL_DELETE: {
127901
+ //! When RETURNING is used, a PROJECTION is the top level operator for INSERTS, UPDATES, and DELETES
127902
+ //! We still need to project all values from these operators so the projection
127903
+ //! on top of them can select from only the table values being inserted.
127904
+ //! TODO: Push down the projections from the returning statement
127905
+ //! TODO: Be careful because you might be adding expressions when a user returns *
127795
127906
  RemoveUnusedColumns remove(binder, context, true);
127796
127907
  remove.VisitOperatorExpressions(op);
127797
127908
  remove.VisitOperator(*op.children[0]);
@@ -149736,6 +149847,10 @@ unique_ptr<DeleteStatement> Transformer::TransformDelete(duckdb_libpgquery::PGNo
149736
149847
  result->using_clauses.push_back(move(using_entry));
149737
149848
  }
149738
149849
  }
149850
+
149851
+ if (stmt->returningList) {
149852
+ Transformer::TransformExpressionList(*(stmt->returningList), result->returning_list);
149853
+ }
149739
149854
  return result;
149740
149855
  }
149741
149856
 
@@ -150500,6 +150615,11 @@ unique_ptr<UpdateStatement> Transformer::TransformUpdate(duckdb_libpgquery::PGNo
150500
150615
  result->expressions.push_back(TransformExpression(target->val));
150501
150616
  }
150502
150617
 
150618
+ // Grab and transform the returning columns from the parser.
150619
+ if (stmt->returningList) {
150620
+ Transformer::TransformExpressionList(*(stmt->returningList), result->returning_list);
150621
+ }
150622
+
150503
150623
  result->condition = TransformExpression(stmt->whereClause);
150504
150624
  return result;
150505
150625
  }
@@ -155700,6 +155820,32 @@ unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateIn
155700
155820
 
155701
155821
 
155702
155822
 
155823
+ //===----------------------------------------------------------------------===//
155824
+ // DuckDB
155825
+ //
155826
+ // duckdb/planner/expression_binder/returning_binder.hpp
155827
+ //
155828
+ //
155829
+ //===----------------------------------------------------------------------===//
155830
+
155831
+
155832
+
155833
+
155834
+
155835
+ namespace duckdb {
155836
+
155837
+ //! The RETURNING binder is responsible for binding expressions within the RETURNING statement
155838
+ class ReturningBinder : public ExpressionBinder {
155839
+ public:
155840
+ ReturningBinder(Binder &binder, ClientContext &context);
155841
+
155842
+ protected:
155843
+ BindResult BindExpression(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth,
155844
+ bool root_expression = false) override;
155845
+ };
155846
+
155847
+ } // namespace duckdb
155848
+
155703
155849
 
155704
155850
 
155705
155851
 
@@ -155774,10 +155920,21 @@ BoundStatement Binder::Bind(DeleteStatement &stmt) {
155774
155920
  LogicalType::ROW_TYPE, ColumnBinding(get.table_index, get.column_ids.size())));
155775
155921
  get.column_ids.push_back(COLUMN_IDENTIFIER_ROW_ID);
155776
155922
 
155777
- result.plan = move(del);
155778
- result.names = {"Count"};
155779
- result.types = {LogicalType::BIGINT};
155780
- this->allow_stream_result = false;
155923
+ if (!stmt.returning_list.empty()) {
155924
+ del->return_chunk = true;
155925
+
155926
+ auto update_table_index = GenerateTableIndex();
155927
+ del->table_index = update_table_index;
155928
+
155929
+ unique_ptr<LogicalOperator> del_as_logicaloperator = move(del);
155930
+ return BindReturning(move(stmt.returning_list), table, update_table_index, move(del_as_logicaloperator),
155931
+ move(result));
155932
+ } else {
155933
+ result.plan = move(del);
155934
+ result.names = {"Count"};
155935
+ result.types = {LogicalType::BIGINT};
155936
+ this->allow_stream_result = false;
155937
+ }
155781
155938
  return result;
155782
155939
  }
155783
155940
 
@@ -156100,31 +156257,6 @@ protected:
156100
156257
 
156101
156258
 
156102
156259
 
156103
- //===----------------------------------------------------------------------===//
156104
- // DuckDB
156105
- //
156106
- // duckdb/planner/expression_binder/returning_binder.hpp
156107
- //
156108
- //
156109
- //===----------------------------------------------------------------------===//
156110
-
156111
-
156112
-
156113
-
156114
-
156115
- namespace duckdb {
156116
-
156117
- //! The RETURNING binder is responsible for binding expressions within the RETURNING statement
156118
- class ReturningBinder : public ExpressionBinder {
156119
- public:
156120
- ReturningBinder(Binder &binder, ClientContext &context);
156121
-
156122
- protected:
156123
- BindResult BindExpression(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth,
156124
- bool root_expression = false) override;
156125
- };
156126
-
156127
- } // namespace duckdb
156128
156260
 
156129
156261
 
156130
156262
  namespace duckdb {
@@ -156245,57 +156377,15 @@ BoundStatement Binder::Bind(InsertStatement &stmt) {
156245
156377
 
156246
156378
  if (!stmt.returning_list.empty()) {
156247
156379
  insert->return_chunk = true;
156248
- // clear result type and names because returning list will update them
156249
156380
  result.types.clear();
156250
156381
  result.names.clear();
156251
-
156252
156382
  auto insert_table_index = GenerateTableIndex();
156253
156383
  insert->table_index = insert_table_index;
156384
+ unique_ptr<LogicalOperator> index_as_logicaloperator = move(insert);
156254
156385
 
156255
- auto binder = Binder::CreateBinder(context);
156256
- auto types = table->GetTypes();
156257
- vector<std::string> names;
156258
- for (auto &col : table->columns) {
156259
- names.push_back(col.name);
156260
- }
156261
-
156262
- binder->bind_context.AddGenericBinding(insert->table_index, stmt.table, names, types);
156263
- ReturningBinder returning_binder(*binder, context);
156264
-
156265
- unique_ptr<LogicalOperator> insert_as_logicaloperator = move(insert);
156266
-
156267
- vector<unique_ptr<Expression>> projection_expressions;
156268
- LogicalType result_type;
156269
- for (auto &returning_expr : stmt.returning_list) {
156270
- auto expr_type = returning_expr->GetExpressionType();
156271
- if (expr_type == ExpressionType::STAR) {
156272
- auto generated_star_list = vector<unique_ptr<ParsedExpression>>();
156273
- binder->bind_context.GenerateAllColumnExpressions((StarExpression &)*returning_expr,
156274
- generated_star_list);
156275
-
156276
- for (auto &star_column : generated_star_list) {
156277
- auto star_expr = returning_binder.Bind(star_column, &result_type);
156278
- result.types.push_back(result_type);
156279
- result.names.push_back(star_expr->GetName());
156280
- projection_expressions.push_back(move(star_expr));
156281
- }
156282
- } else {
156283
- auto expr = returning_binder.Bind(returning_expr, &result_type);
156284
- result.names.push_back(expr->GetName());
156285
- result.types.push_back(result_type);
156286
- projection_expressions.push_back(move(expr));
156287
- }
156288
- }
156289
-
156290
- auto projection = make_unique<LogicalProjection>(GenerateTableIndex(), move(projection_expressions));
156291
- projection->AddChild(move(insert_as_logicaloperator));
156292
- result.plan = move(projection);
156293
- D_ASSERT(result.types.size() == result.names.size());
156294
- this->allow_stream_result = true;
156295
- return result;
156386
+ return BindReturning(move(stmt.returning_list), table, insert_table_index, move(index_as_logicaloperator),
156387
+ move(result));
156296
156388
  } else {
156297
- insert->table_index = 0;
156298
- insert->return_chunk = false;
156299
156389
  D_ASSERT(result.types.size() == result.names.size());
156300
156390
  result.plan = move(insert);
156301
156391
  this->allow_stream_result = false;
@@ -156750,6 +156840,8 @@ static void BindUpdateConstraints(TableCatalogEntry &table, LogicalGet &get, Log
156750
156840
  }
156751
156841
  // for index updates we always turn any update into an insert and a delete
156752
156842
  // we thus need all the columns to be available, hence we check if the update touches any index columns
156843
+ // If the returning keyword is used, we need access to the whole row in case the user requests it.
156844
+ // Therefore switch the update to a delete and insert.
156753
156845
  update.update_is_del_and_insert = false;
156754
156846
  table.storage->info->indexes.Scan([&](Index &index) {
156755
156847
  if (index.IndexIsUpdated(update.columns)) {
@@ -156767,8 +156859,9 @@ static void BindUpdateConstraints(TableCatalogEntry &table, LogicalGet &get, Log
156767
156859
  }
156768
156860
  }
156769
156861
 
156770
- if (update.update_is_del_and_insert) {
156771
- // the update updates a column required by an index, push projections for all columns
156862
+ if (update.update_is_del_and_insert || update.return_chunk) {
156863
+ // the update updates a column required by an index or requires returning the updated rows,
156864
+ // push projections for all columns
156772
156865
  unordered_set<column_t> all_columns;
156773
156866
  for (idx_t i = 0; i < table.storage->column_definitions.size(); i++) {
156774
156867
  all_columns.insert(i);
@@ -156806,6 +156899,11 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
156806
156899
  this->read_only = false;
156807
156900
  }
156808
156901
  auto update = make_unique<LogicalUpdate>(table);
156902
+
156903
+ // set return_chunk boolean early because it needs uses update_is_del_and_insert logic
156904
+ if (!stmt.returning_list.empty()) {
156905
+ update->return_chunk = true;
156906
+ }
156809
156907
  // bind the default values
156810
156908
  BindDefaultValues(table->columns, update->bound_defaults);
156811
156909
 
@@ -156824,6 +156922,7 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
156824
156922
 
156825
156923
  auto proj_index = GenerateTableIndex();
156826
156924
  vector<unique_ptr<Expression>> projection_expressions;
156925
+
156827
156926
  for (idx_t i = 0; i < stmt.columns.size(); i++) {
156828
156927
  auto &colname = stmt.columns[i];
156829
156928
  auto &expr = stmt.expressions[i];
@@ -156849,6 +156948,7 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
156849
156948
  projection_expressions.push_back(move(bound_expr));
156850
156949
  }
156851
156950
  }
156951
+
156852
156952
  // now create the projection
156853
156953
  auto proj = make_unique<LogicalProjection>(proj_index, move(projection_expressions));
156854
156954
  proj->AddChild(move(root));
@@ -156864,10 +156964,21 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
156864
156964
  // set the projection as child of the update node and finalize the result
156865
156965
  update->AddChild(move(proj));
156866
156966
 
156867
- result.names = {"Count"};
156868
- result.types = {LogicalType::BIGINT};
156869
- result.plan = move(update);
156870
- this->allow_stream_result = false;
156967
+ if (!stmt.returning_list.empty()) {
156968
+ auto update_table_index = GenerateTableIndex();
156969
+ update->table_index = update_table_index;
156970
+ unique_ptr<LogicalOperator> update_as_logicaloperator = move(update);
156971
+
156972
+ return BindReturning(move(stmt.returning_list), table, update_table_index, move(update_as_logicaloperator),
156973
+ move(result));
156974
+
156975
+ } else {
156976
+ update->table_index = 0;
156977
+ result.names = {"Count"};
156978
+ result.types = {LogicalType::BIGINT};
156979
+ result.plan = move(update);
156980
+ this->allow_stream_result = false;
156981
+ }
156871
156982
  return result;
156872
156983
  }
156873
156984
 
@@ -158130,6 +158241,7 @@ unique_ptr<LogicalOperator> Binder::CreatePlan(BoundTableFunction &ref) {
158130
158241
 
158131
158242
 
158132
158243
 
158244
+
158133
158245
  #include <algorithm>
158134
158246
 
158135
158247
 
@@ -158498,6 +158610,53 @@ string Binder::FormatErrorRecursive(idx_t query_location, const string &message,
158498
158610
  return context.FormatErrorRecursive(message, values);
158499
158611
  }
158500
158612
 
158613
+ BoundStatement Binder::BindReturning(vector<unique_ptr<ParsedExpression>> returning_list, TableCatalogEntry *table,
158614
+ idx_t update_table_index, unique_ptr<LogicalOperator> child_operator,
158615
+ BoundStatement result) {
158616
+
158617
+ vector<LogicalType> types;
158618
+ vector<std::string> names;
158619
+
158620
+ auto binder = Binder::CreateBinder(context);
158621
+
158622
+ for (auto &col : table->columns) {
158623
+ names.push_back(col.name);
158624
+ types.push_back(col.type);
158625
+ }
158626
+
158627
+ binder->bind_context.AddGenericBinding(update_table_index, table->name, names, types);
158628
+ ReturningBinder returning_binder(*binder, context);
158629
+
158630
+ vector<unique_ptr<Expression>> projection_expressions;
158631
+ LogicalType result_type;
158632
+ for (auto &returning_expr : returning_list) {
158633
+ auto expr_type = returning_expr->GetExpressionType();
158634
+ if (expr_type == ExpressionType::STAR) {
158635
+ auto generated_star_list = vector<unique_ptr<ParsedExpression>>();
158636
+ binder->bind_context.GenerateAllColumnExpressions((StarExpression &)*returning_expr, generated_star_list);
158637
+
158638
+ for (auto &star_column : generated_star_list) {
158639
+ auto star_expr = returning_binder.Bind(star_column, &result_type);
158640
+ result.types.push_back(result_type);
158641
+ result.names.push_back(star_expr->GetName());
158642
+ projection_expressions.push_back(move(star_expr));
158643
+ }
158644
+ } else {
158645
+ auto expr = returning_binder.Bind(returning_expr, &result_type);
158646
+ result.names.push_back(expr->GetName());
158647
+ result.types.push_back(result_type);
158648
+ projection_expressions.push_back(move(expr));
158649
+ }
158650
+ }
158651
+
158652
+ auto projection = make_unique<LogicalProjection>(GenerateTableIndex(), move(projection_expressions));
158653
+ projection->AddChild(move(child_operator));
158654
+ D_ASSERT(result.types.size() == result.names.size());
158655
+ result.plan = move(projection);
158656
+ this->allow_stream_result = true;
158657
+ return result;
158658
+ }
158659
+
158501
158660
  } // namespace duckdb
158502
158661
 
158503
158662
 
package/src/duckdb.hpp CHANGED
@@ -11,8 +11,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
13
  #define DUCKDB_AMALGAMATION_EXTENDED 1
14
- #define DUCKDB_SOURCE_ID "041fb2cc7"
15
- #define DUCKDB_VERSION "v0.3.3-dev1232"
14
+ #define DUCKDB_SOURCE_ID "a8cf83273"
15
+ #define DUCKDB_VERSION "v0.3.3-dev1251"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -13542,6 +13542,9 @@ private:
13542
13542
  BoundStatement Bind(ExportStatement &stmt);
13543
13543
  BoundStatement Bind(SetStatement &stmt);
13544
13544
  BoundStatement Bind(LoadStatement &stmt);
13545
+ BoundStatement BindReturning(vector<unique_ptr<ParsedExpression>> returning_list, TableCatalogEntry *table,
13546
+ idx_t update_table_index, unique_ptr<LogicalOperator> child_operator,
13547
+ BoundStatement result);
13545
13548
 
13546
13549
  unique_ptr<QueryNode> BindTableMacro(FunctionExpression &function, TableMacroCatalogEntry *macro_func, idx_t depth);
13547
13550