duckdb 0.6.2-dev2085.0 → 0.6.2-dev2094.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-dev2085.0",
5
+ "version": "0.6.2-dev2094.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -211,6 +211,19 @@ void ParquetWriter::SetSchemaProperties(const LogicalType &duckdb_type,
211
211
  }
212
212
  }
213
213
 
214
+ void VerifyUniqueNames(const vector<string> &names) {
215
+ #ifdef DEBUG
216
+ unordered_set<string> name_set;
217
+ name_set.reserve(names.size());
218
+ for (auto &column : names) {
219
+ auto res = name_set.insert(column);
220
+ D_ASSERT(res.second == true);
221
+ }
222
+ // If there would be duplicates, these sizes would differ
223
+ D_ASSERT(name_set.size() == names.size());
224
+ #endif
225
+ }
226
+
214
227
  ParquetWriter::ParquetWriter(FileSystem &fs, string file_name_p, FileOpener *file_opener_p, vector<LogicalType> types_p,
215
228
  vector<string> names_p, CompressionCodec::type codec)
216
229
  : file_name(std::move(file_name_p)), sql_types(std::move(types_p)), column_names(std::move(names_p)), codec(codec) {
@@ -237,10 +250,13 @@ ParquetWriter::ParquetWriter(FileSystem &fs, string file_name_p, FileOpener *fil
237
250
  file_meta_data.schema[0].repetition_type = duckdb_parquet::format::FieldRepetitionType::REQUIRED;
238
251
  file_meta_data.schema[0].__isset.repetition_type = true;
239
252
 
253
+ auto &unique_names = column_names;
254
+ VerifyUniqueNames(unique_names);
255
+
240
256
  vector<string> schema_path;
241
257
  for (idx_t i = 0; i < sql_types.size(); i++) {
242
258
  column_writers.push_back(ColumnWriter::CreateWriterRecursive(file_meta_data.schema, *this, sql_types[i],
243
- column_names[i], schema_path));
259
+ unique_names[i], schema_path));
244
260
  }
245
261
  }
246
262
 
@@ -300,37 +300,13 @@ unique_ptr<CatalogEntry> DuckTableEntry::AddColumn(ClientContext &context, AddCo
300
300
  return make_unique<DuckTableEntry>(catalog, schema, (BoundCreateTableInfo *)bound_create_info.get(), new_storage);
301
301
  }
302
302
 
303
- unique_ptr<CatalogEntry> DuckTableEntry::RemoveColumn(ClientContext &context, RemoveColumnInfo &info) {
304
- auto removed_index = GetColumnIndex(info.removed_column, info.if_column_exists);
305
- if (!removed_index.IsValid()) {
306
- if (!info.if_column_exists) {
307
- throw CatalogException("Cannot drop column: rowid column cannot be dropped");
308
- }
309
- return nullptr;
310
- }
311
-
312
- auto create_info = make_unique<CreateTableInfo>(schema, name);
313
- create_info->temporary = temporary;
314
-
315
- logical_index_set_t removed_columns;
316
- if (column_dependency_manager.HasDependents(removed_index)) {
317
- removed_columns = column_dependency_manager.GetDependents(removed_index);
318
- }
319
- if (!removed_columns.empty() && !info.cascade) {
320
- throw CatalogException("Cannot drop column: column is a dependency of 1 or more generated column(s)");
321
- }
322
- for (auto &col : columns.Logical()) {
323
- if (col.Logical() == removed_index || removed_columns.count(col.Logical())) {
324
- continue;
325
- }
326
- create_info->columns.AddColumn(col.Copy());
327
- }
328
- if (create_info->columns.empty()) {
329
- throw CatalogException("Cannot drop column: table only has one column remaining!");
330
- }
331
- auto adjusted_indices = column_dependency_manager.RemoveColumn(removed_index, columns.LogicalColumnCount());
303
+ void DuckTableEntry::UpdateConstraintsOnColumnDrop(const LogicalIndex &removed_index,
304
+ const vector<LogicalIndex> &adjusted_indices,
305
+ const RemoveColumnInfo &info, CreateTableInfo &create_info,
306
+ bool is_generated) {
332
307
  // handle constraints for the new table
333
308
  D_ASSERT(constraints.size() == bound_constraints.size());
309
+
334
310
  for (idx_t constr_idx = 0; constr_idx < constraints.size(); constr_idx++) {
335
311
  auto &constraint = constraints[constr_idx];
336
312
  auto &bound_constraint = bound_constraints[constr_idx];
@@ -342,14 +318,20 @@ unique_ptr<CatalogEntry> DuckTableEntry::RemoveColumn(ClientContext &context, Re
342
318
  // the constraint is not about this column: we need to copy it
343
319
  // we might need to shift the index back by one though, to account for the removed column
344
320
  auto new_index = adjusted_indices[not_null_index.index];
345
- create_info->constraints.push_back(make_unique<NotNullConstraint>(new_index));
321
+ create_info.constraints.push_back(make_unique<NotNullConstraint>(new_index));
346
322
  }
347
323
  break;
348
324
  }
349
325
  case ConstraintType::CHECK: {
326
+ // Generated columns can not be part of an index
350
327
  // CHECK constraint
351
328
  auto &bound_check = (BoundCheckConstraint &)*bound_constraint;
352
329
  // check if the removed column is part of the check constraint
330
+ if (is_generated) {
331
+ // generated columns can not be referenced by constraints, we can just add the constraint back
332
+ create_info.constraints.push_back(constraint->Copy());
333
+ break;
334
+ }
353
335
  auto physical_index = columns.LogicalToPhysical(removed_index);
354
336
  if (bound_check.bound_columns.find(physical_index) != bound_check.bound_columns.end()) {
355
337
  if (bound_check.bound_columns.size() > 1) {
@@ -362,7 +344,7 @@ unique_ptr<CatalogEntry> DuckTableEntry::RemoveColumn(ClientContext &context, Re
362
344
  }
363
345
  } else {
364
346
  // check constraint does not concern the removed column: simply re-add it
365
- create_info->constraints.push_back(constraint->Copy());
347
+ create_info.constraints.push_back(constraint->Copy());
366
348
  }
367
349
  break;
368
350
  }
@@ -377,7 +359,7 @@ unique_ptr<CatalogEntry> DuckTableEntry::RemoveColumn(ClientContext &context, Re
377
359
  }
378
360
  unique.index = adjusted_indices[unique.index.index];
379
361
  }
380
- create_info->constraints.push_back(std::move(copy));
362
+ create_info.constraints.push_back(std::move(copy));
381
363
  break;
382
364
  }
383
365
  case ConstraintType::FOREIGN_KEY: {
@@ -398,13 +380,50 @@ unique_ptr<CatalogEntry> DuckTableEntry::RemoveColumn(ClientContext &context, Re
398
380
  info.removed_column);
399
381
  }
400
382
  }
401
- create_info->constraints.push_back(std::move(copy));
383
+ create_info.constraints.push_back(std::move(copy));
402
384
  break;
403
385
  }
404
386
  default:
405
387
  throw InternalException("Unsupported constraint for entry!");
406
388
  }
407
389
  }
390
+ }
391
+
392
+ unique_ptr<CatalogEntry> DuckTableEntry::RemoveColumn(ClientContext &context, RemoveColumnInfo &info) {
393
+ auto removed_index = GetColumnIndex(info.removed_column, info.if_column_exists);
394
+ if (!removed_index.IsValid()) {
395
+ if (!info.if_column_exists) {
396
+ throw CatalogException("Cannot drop column: rowid column cannot be dropped");
397
+ }
398
+ return nullptr;
399
+ }
400
+
401
+ auto create_info = make_unique<CreateTableInfo>(schema, name);
402
+ create_info->temporary = temporary;
403
+
404
+ logical_index_set_t removed_columns;
405
+ if (column_dependency_manager.HasDependents(removed_index)) {
406
+ removed_columns = column_dependency_manager.GetDependents(removed_index);
407
+ }
408
+ if (!removed_columns.empty() && !info.cascade) {
409
+ throw CatalogException("Cannot drop column: column is a dependency of 1 or more generated column(s)");
410
+ }
411
+ bool dropped_column_is_generated = false;
412
+ for (auto &col : columns.Logical()) {
413
+ if (col.Logical() == removed_index || removed_columns.count(col.Logical())) {
414
+ if (col.Generated()) {
415
+ dropped_column_is_generated = true;
416
+ }
417
+ continue;
418
+ }
419
+ create_info->columns.AddColumn(col.Copy());
420
+ }
421
+ if (create_info->columns.empty()) {
422
+ throw CatalogException("Cannot drop column: table only has one column remaining!");
423
+ }
424
+ auto adjusted_indices = column_dependency_manager.RemoveColumn(removed_index, columns.LogicalColumnCount());
425
+
426
+ UpdateConstraintsOnColumnDrop(removed_index, adjusted_indices, info, *create_info, dropped_column_is_generated);
408
427
 
409
428
  auto binder = Binder::CreateBinder(context);
410
429
  auto bound_create_info = binder->BindCreateTableInfo(std::move(create_info));
@@ -1,8 +1,8 @@
1
1
  #ifndef DUCKDB_VERSION
2
- #define DUCKDB_VERSION "0.6.2-dev2085"
2
+ #define DUCKDB_VERSION "0.6.2-dev2094"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "a038924fb3"
5
+ #define DUCKDB_SOURCE_ID "4552228a14"
6
6
  #endif
7
7
  #include "duckdb/function/table/system_functions.hpp"
8
8
  #include "duckdb/main/database.hpp"
@@ -57,6 +57,9 @@ private:
57
57
  unique_ptr<CatalogEntry> AddForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info);
58
58
  unique_ptr<CatalogEntry> DropForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info);
59
59
 
60
+ void UpdateConstraintsOnColumnDrop(const LogicalIndex &removed_index, const vector<LogicalIndex> &adjusted_indices,
61
+ const RemoveColumnInfo &info, CreateTableInfo &create_info, bool is_generated);
62
+
60
63
  private:
61
64
  //! A reference to the underlying storage unit used for this table
62
65
  std::shared_ptr<DataTable> storage;
@@ -33,6 +33,34 @@ static vector<idx_t> ColumnListToIndices(const vector<bool> &vec) {
33
33
  return ret;
34
34
  }
35
35
 
36
+ vector<string> GetUniqueNames(const vector<string> &original_names) {
37
+ unordered_set<string> name_set;
38
+ vector<string> unique_names;
39
+ unique_names.reserve(original_names.size());
40
+
41
+ for (auto &name : original_names) {
42
+ auto insert_result = name_set.insert(name);
43
+ if (insert_result.second == false) {
44
+ // Could not be inserted, name already exists
45
+ idx_t index = 1;
46
+ string postfixed_name;
47
+ while (true) {
48
+ postfixed_name = StringUtil::Format("%s:%d", name, index);
49
+ auto res = name_set.insert(postfixed_name);
50
+ if (!res.second) {
51
+ index++;
52
+ continue;
53
+ }
54
+ break;
55
+ }
56
+ unique_names.push_back(postfixed_name);
57
+ } else {
58
+ unique_names.push_back(name);
59
+ }
60
+ }
61
+ return unique_names;
62
+ }
63
+
36
64
  BoundStatement Binder::BindCopyTo(CopyStatement &stmt) {
37
65
  // COPY TO a file
38
66
  auto &config = DBConfig::GetConfig(context);
@@ -99,8 +127,10 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) {
99
127
  use_tmp_file = is_file_and_exists && !per_thread_output && partition_cols.empty() && !is_stdout;
100
128
  }
101
129
 
130
+ auto unique_column_names = GetUniqueNames(select_node.names);
131
+
102
132
  auto function_data =
103
- copy_function->function.copy_to_bind(context, *stmt.info, select_node.names, select_node.types);
133
+ copy_function->function.copy_to_bind(context, *stmt.info, unique_column_names, select_node.types);
104
134
  // now create the copy information
105
135
  auto copy = make_unique<LogicalCopyToFile>(copy_function->function, std::move(function_data));
106
136
  copy->file_path = stmt.info->file_path;
@@ -110,7 +140,8 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) {
110
140
  copy->per_thread_output = per_thread_output;
111
141
  copy->partition_output = !partition_cols.empty();
112
142
  copy->partition_columns = std::move(partition_cols);
113
- copy->names = select_node.names;
143
+
144
+ copy->names = unique_column_names;
114
145
  copy->expected_types = select_node.types;
115
146
 
116
147
  copy->AddChild(std::move(select_node.plan));