duckdb 0.7.1-dev19.0 → 0.7.1-dev240.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.
Files changed (102) hide show
  1. package/binding.gyp +7 -7
  2. package/package.json +1 -1
  3. package/src/duckdb/extension/json/buffered_json_reader.cpp +50 -9
  4. package/src/duckdb/extension/json/include/buffered_json_reader.hpp +7 -2
  5. package/src/duckdb/extension/json/include/json_scan.hpp +29 -10
  6. package/src/duckdb/extension/json/json_functions/copy_json.cpp +35 -22
  7. package/src/duckdb/extension/json/json_functions/json_create.cpp +8 -8
  8. package/src/duckdb/extension/json/json_functions/json_transform.cpp +46 -8
  9. package/src/duckdb/extension/json/json_functions/read_json.cpp +104 -49
  10. package/src/duckdb/extension/json/json_functions/read_json_objects.cpp +5 -3
  11. package/src/duckdb/extension/json/json_functions.cpp +6 -0
  12. package/src/duckdb/extension/json/json_scan.cpp +144 -34
  13. package/src/duckdb/extension/parquet/parquet-extension.cpp +3 -2
  14. package/src/duckdb/src/common/enums/logical_operator_type.cpp +2 -0
  15. package/src/duckdb/src/common/enums/physical_operator_type.cpp +2 -0
  16. package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
  17. package/src/duckdb/src/common/file_system.cpp +14 -0
  18. package/src/duckdb/src/common/hive_partitioning.cpp +1 -0
  19. package/src/duckdb/src/common/operator/cast_operators.cpp +14 -8
  20. package/src/duckdb/src/common/printer.cpp +1 -1
  21. package/src/duckdb/src/common/types/time.cpp +1 -1
  22. package/src/duckdb/src/common/types/timestamp.cpp +35 -4
  23. package/src/duckdb/src/common/types.cpp +36 -10
  24. package/src/duckdb/src/execution/column_binding_resolver.cpp +5 -2
  25. package/src/duckdb/src/execution/operator/join/physical_iejoin.cpp +7 -9
  26. package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +6 -11
  27. package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +13 -13
  28. package/src/duckdb/src/execution/operator/persistent/parallel_csv_reader.cpp +1 -1
  29. package/src/duckdb/src/execution/operator/schema/physical_detach.cpp +37 -0
  30. package/src/duckdb/src/execution/operator/schema/physical_drop.cpp +0 -5
  31. package/src/duckdb/src/execution/physical_plan/plan_simple.cpp +4 -0
  32. package/src/duckdb/src/execution/physical_plan_generator.cpp +1 -0
  33. package/src/duckdb/src/function/pragma/pragma_queries.cpp +36 -9
  34. package/src/duckdb/src/function/table/read_csv.cpp +15 -4
  35. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  36. package/src/duckdb/src/include/duckdb/common/enums/logical_operator_type.hpp +1 -0
  37. package/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp +1 -0
  38. package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +3 -2
  39. package/src/duckdb/src/include/duckdb/common/exception.hpp +10 -0
  40. package/src/duckdb/src/include/duckdb/common/file_system.hpp +1 -0
  41. package/src/duckdb/src/include/duckdb/common/hive_partitioning.hpp +9 -1
  42. package/src/duckdb/src/include/duckdb/common/radix_partitioning.hpp +4 -4
  43. package/src/duckdb/src/include/duckdb/common/types/timestamp.hpp +5 -1
  44. package/src/duckdb/src/include/duckdb/execution/operator/persistent/base_csv_reader.hpp +1 -3
  45. package/src/duckdb/src/include/duckdb/execution/operator/persistent/buffered_csv_reader.hpp +0 -2
  46. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +2 -0
  47. package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_detach.hpp +32 -0
  48. package/src/duckdb/src/include/duckdb/main/client_data.hpp +2 -2
  49. package/src/duckdb/src/include/duckdb/main/config.hpp +0 -3
  50. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_database_info.hpp +0 -4
  51. package/src/duckdb/src/include/duckdb/parser/parsed_data/detach_info.hpp +32 -0
  52. package/src/duckdb/src/include/duckdb/parser/query_node/select_node.hpp +1 -1
  53. package/src/duckdb/src/include/duckdb/parser/sql_statement.hpp +2 -2
  54. package/src/duckdb/src/include/duckdb/parser/statement/copy_statement.hpp +1 -1
  55. package/src/duckdb/src/include/duckdb/parser/statement/detach_statement.hpp +29 -0
  56. package/src/duckdb/src/include/duckdb/parser/statement/list.hpp +1 -0
  57. package/src/duckdb/src/include/duckdb/parser/statement/select_statement.hpp +3 -3
  58. package/src/duckdb/src/include/duckdb/parser/tableref/subqueryref.hpp +1 -1
  59. package/src/duckdb/src/include/duckdb/parser/tokens.hpp +1 -0
  60. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +1 -0
  61. package/src/duckdb/src/include/duckdb/planner/binder.hpp +1 -0
  62. package/src/duckdb/src/include/duckdb/planner/operator/logical_execute.hpp +1 -5
  63. package/src/duckdb/src/include/duckdb/planner/operator/logical_show.hpp +1 -2
  64. package/src/duckdb/src/include/duckdb/storage/storage_extension.hpp +7 -0
  65. package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +2 -0
  66. package/src/duckdb/src/main/client_context.cpp +2 -0
  67. package/src/duckdb/src/main/extension/extension_alias.cpp +2 -1
  68. package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +2 -6
  69. package/src/duckdb/src/parser/statement/copy_statement.cpp +2 -13
  70. package/src/duckdb/src/parser/statement/delete_statement.cpp +3 -0
  71. package/src/duckdb/src/parser/statement/detach_statement.cpp +15 -0
  72. package/src/duckdb/src/parser/statement/insert_statement.cpp +9 -0
  73. package/src/duckdb/src/parser/statement/update_statement.cpp +3 -0
  74. package/src/duckdb/src/parser/transform/expression/transform_case.cpp +3 -3
  75. package/src/duckdb/src/parser/transform/statement/transform_create_database.cpp +0 -1
  76. package/src/duckdb/src/parser/transform/statement/transform_detach.cpp +19 -0
  77. package/src/duckdb/src/parser/transformer.cpp +2 -0
  78. package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +3 -0
  79. package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +6 -3
  80. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +16 -14
  81. package/src/duckdb/src/planner/binder/statement/bind_detach.cpp +19 -0
  82. package/src/duckdb/src/planner/binder/statement/bind_drop.cpp +29 -4
  83. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +22 -1
  84. package/src/duckdb/src/planner/binder/tableref/bind_joinref.cpp +2 -1
  85. package/src/duckdb/src/planner/binder.cpp +2 -0
  86. package/src/duckdb/src/planner/expression_binder/lateral_binder.cpp +21 -5
  87. package/src/duckdb/src/planner/logical_operator.cpp +4 -0
  88. package/src/duckdb/src/planner/planner.cpp +1 -0
  89. package/src/duckdb/src/storage/storage_info.cpp +2 -1
  90. package/src/duckdb/src/storage/table/column_data.cpp +4 -2
  91. package/src/duckdb/src/storage/table/update_segment.cpp +15 -0
  92. package/src/duckdb/third_party/fmt/include/fmt/core.h +1 -2
  93. package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +1 -0
  94. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +14 -0
  95. package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +530 -1006
  96. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +17659 -17626
  97. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +4 -4
  98. package/src/duckdb/ub_src_execution_operator_schema.cpp +2 -0
  99. package/src/duckdb/ub_src_parser_statement.cpp +2 -0
  100. package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
  101. package/src/duckdb/ub_src_planner_binder_statement.cpp +2 -0
  102. package/src/duckdb/src/include/duckdb/function/create_database_extension.hpp +0 -37
@@ -100,6 +100,8 @@ string LogicalOperatorToString(LogicalOperatorType type) {
100
100
  return "CREATE_SCHEMA";
101
101
  case LogicalOperatorType::LOGICAL_ATTACH:
102
102
  return "ATTACH";
103
+ case LogicalOperatorType::LOGICAL_DETACH:
104
+ return "ATTACH";
103
105
  case LogicalOperatorType::LOGICAL_DROP:
104
106
  return "DROP";
105
107
  case LogicalOperatorType::LOGICAL_PRAGMA:
@@ -133,6 +133,8 @@ string PhysicalOperatorToString(PhysicalOperatorType type) {
133
133
  return "CREATE_TYPE";
134
134
  case PhysicalOperatorType::ATTACH:
135
135
  return "ATTACH";
136
+ case PhysicalOperatorType::DETACH:
137
+ return "DETACH";
136
138
  case PhysicalOperatorType::RESULT_COLLECTOR:
137
139
  return "RESULT_COLLECTOR";
138
140
  case PhysicalOperatorType::EXTENSION:
@@ -57,6 +57,8 @@ string StatementTypeToString(StatementType type) {
57
57
  return "LOGICAL_PLAN";
58
58
  case StatementType::ATTACH_STATEMENT:
59
59
  return "ATTACH";
60
+ case StatementType::DETACH_STATEMENT:
61
+ return "DETACH";
60
62
  case StatementType::INVALID_STATEMENT:
61
63
  break;
62
64
  }
@@ -335,6 +335,20 @@ bool FileSystem::CanHandleFile(const string &fpath) {
335
335
  throw NotImplementedException("%s: CanHandleFile is not implemented!", GetName());
336
336
  }
337
337
 
338
+ IOException FileSystem::MissingFileException(const string &file_path, ClientContext &context) {
339
+ const string prefixes[] = {"http://", "https://", "s3://"};
340
+ for (auto &prefix : prefixes) {
341
+ if (StringUtil::StartsWith(file_path, prefix)) {
342
+ if (!context.db->LoadedExtensions().count("httpfs")) {
343
+ return MissingExtensionException("No files found that match the pattern \"%s\", because the httpfs "
344
+ "extension is not loaded. Try loading the extension: LOAD HTTPFS",
345
+ file_path);
346
+ }
347
+ }
348
+ }
349
+ return IOException("No files found that match the pattern \"%s\"", file_path);
350
+ }
351
+
338
352
  void FileSystem::Seek(FileHandle &handle, idx_t location) {
339
353
  throw NotImplementedException("%s: Seek is not implemented!", GetName());
340
354
  }
@@ -150,6 +150,7 @@ HivePartitionedColumnData::HivePartitionedColumnData(const HivePartitionedColumn
150
150
  void HivePartitionedColumnData::ComputePartitionIndices(PartitionedColumnDataAppendState &state, DataChunk &input) {
151
151
  Vector hashes(LogicalType::HASH, input.size());
152
152
  input.Hash(group_by_columns, hashes);
153
+ hashes.Flatten(input.size());
153
154
 
154
155
  for (idx_t i = 0; i < input.size(); i++) {
155
156
  HivePartitionKey key;
@@ -946,13 +946,13 @@ static bool IntegerCastLoop(const char *buf, idx_t len, T &result, bool strict)
946
946
  ExponentData exponent {0, false};
947
947
  int negative = buf[pos] == '-';
948
948
  if (negative) {
949
- if (!IntegerCastLoop<ExponentData, true, false, IntegerCastOperation>(buf + pos, len - pos,
950
- exponent, strict)) {
949
+ if (!IntegerCastLoop<ExponentData, true, false, IntegerCastOperation, decimal_separator>(
950
+ buf + pos, len - pos, exponent, strict)) {
951
951
  return false;
952
952
  }
953
953
  } else {
954
- if (!IntegerCastLoop<ExponentData, false, false, IntegerCastOperation>(buf + pos, len - pos,
955
- exponent, strict)) {
954
+ if (!IntegerCastLoop<ExponentData, false, false, IntegerCastOperation, decimal_separator>(
955
+ buf + pos, len - pos, exponent, strict)) {
956
956
  return false;
957
957
  }
958
958
  }
@@ -1554,16 +1554,22 @@ dtime_t Cast::Operation(string_t input) {
1554
1554
  //===--------------------------------------------------------------------===//
1555
1555
  template <>
1556
1556
  bool TryCastErrorMessage::Operation(string_t input, timestamp_t &result, string *error_message, bool strict) {
1557
- if (!TryCast::Operation<string_t, timestamp_t>(input, result, strict)) {
1557
+ auto cast_result = Timestamp::TryConvertTimestamp(input.GetDataUnsafe(), input.GetSize(), result);
1558
+ if (cast_result == TimestampCastResult::SUCCESS) {
1559
+ return true;
1560
+ }
1561
+ if (cast_result == TimestampCastResult::ERROR_INCORRECT_FORMAT) {
1558
1562
  HandleCastError::AssignError(Timestamp::ConversionError(input), error_message);
1559
- return false;
1563
+ } else {
1564
+ HandleCastError::AssignError(Timestamp::UnsupportedTimezoneError(input), error_message);
1560
1565
  }
1561
- return true;
1566
+ return false;
1562
1567
  }
1563
1568
 
1564
1569
  template <>
1565
1570
  bool TryCast::Operation(string_t input, timestamp_t &result, bool strict) {
1566
- return Timestamp::TryConvertTimestamp(input.GetDataUnsafe(), input.GetSize(), result);
1571
+ return Timestamp::TryConvertTimestamp(input.GetDataUnsafe(), input.GetSize(), result) ==
1572
+ TimestampCastResult::SUCCESS;
1567
1573
  }
1568
1574
 
1569
1575
  template <>
@@ -65,7 +65,7 @@ idx_t Printer::TerminalWidth() {
65
65
  int columns, rows;
66
66
 
67
67
  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
68
- rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
68
+ rows = csbi.srWindow.Right - csbi.srWindow.Left + 1;
69
69
  return rows;
70
70
  #else
71
71
  struct winsize w;
@@ -115,7 +115,7 @@ bool Time::TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &resul
115
115
  if (!strict) {
116
116
  // last chance, check if we can parse as timestamp
117
117
  timestamp_t timestamp;
118
- if (Timestamp::TryConvertTimestamp(buf, len, timestamp)) {
118
+ if (Timestamp::TryConvertTimestamp(buf, len, timestamp) == TimestampCastResult::SUCCESS) {
119
119
  if (!Timestamp::IsFinite(timestamp)) {
120
120
  return false;
121
121
  }
@@ -88,11 +88,27 @@ bool Timestamp::TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &r
88
88
  return true;
89
89
  }
90
90
 
91
- bool Timestamp::TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result) {
91
+ TimestampCastResult Timestamp::TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result) {
92
92
  string_t tz(nullptr, 0);
93
93
  bool has_offset = false;
94
94
  // We don't understand TZ without an extension, so fail if one was provided.
95
- return TryConvertTimestampTZ(str, len, result, has_offset, tz) && !tz.GetSize();
95
+ auto success = TryConvertTimestampTZ(str, len, result, has_offset, tz);
96
+ if (!success) {
97
+ return TimestampCastResult::ERROR_INCORRECT_FORMAT;
98
+ }
99
+ if (tz.GetSize() == 0) {
100
+ // no timezone provided - success!
101
+ return TimestampCastResult::SUCCESS;
102
+ }
103
+ if (tz.GetSize() == 3) {
104
+ // we can ONLY handle UTC without ICU being loaded
105
+ auto tz_ptr = tz.GetDataUnsafe();
106
+ if ((tz_ptr[0] == 'u' || tz_ptr[0] == 'U') && (tz_ptr[1] == 't' || tz_ptr[1] == 'T') &&
107
+ (tz_ptr[2] == 'c' || tz_ptr[2] == 'C')) {
108
+ return TimestampCastResult::SUCCESS;
109
+ }
110
+ }
111
+ return TimestampCastResult::ERROR_NON_UTC_TIMEZONE;
96
112
  }
97
113
 
98
114
  string Timestamp::ConversionError(const string &str) {
@@ -101,16 +117,31 @@ string Timestamp::ConversionError(const string &str) {
101
117
  str);
102
118
  }
103
119
 
120
+ string Timestamp::UnsupportedTimezoneError(const string &str) {
121
+ return StringUtil::Format("timestamp field value \"%s\" has a timestamp that is not UTC.\nUse the TIMESTAMPTZ type "
122
+ "with the ICU extension loaded to handle non-UTC timestamps.",
123
+ str);
124
+ }
125
+
104
126
  string Timestamp::ConversionError(string_t str) {
105
127
  return Timestamp::ConversionError(str.GetString());
106
128
  }
107
129
 
130
+ string Timestamp::UnsupportedTimezoneError(string_t str) {
131
+ return Timestamp::UnsupportedTimezoneError(str.GetString());
132
+ }
133
+
108
134
  timestamp_t Timestamp::FromCString(const char *str, idx_t len) {
109
135
  timestamp_t result;
110
- if (!Timestamp::TryConvertTimestamp(str, len, result)) {
136
+ auto cast_result = Timestamp::TryConvertTimestamp(str, len, result);
137
+ if (cast_result == TimestampCastResult::SUCCESS) {
138
+ return result;
139
+ }
140
+ if (cast_result == TimestampCastResult::ERROR_NON_UTC_TIMEZONE) {
141
+ throw ConversionException(Timestamp::UnsupportedTimezoneError(string(str, len)));
142
+ } else {
111
143
  throw ConversionException(Timestamp::ConversionError(string(str, len)));
112
144
  }
113
- return result;
114
145
  }
115
146
 
116
147
  bool Timestamp::TryParseUTCOffset(const char *str, idx_t &pos, idx_t len, int &hour_offset, int &minute_offset) {
@@ -504,11 +504,32 @@ LogicalType TransformStringToLogicalType(const string &str) {
504
504
  return Parser::ParseColumnList("dummy " + str).GetColumn(LogicalIndex(0)).Type();
505
505
  }
506
506
 
507
+ LogicalType GetUserTypeRecursive(const LogicalType &type, ClientContext &context) {
508
+ if (type.id() == LogicalTypeId::USER && type.HasAlias()) {
509
+ return Catalog::GetSystemCatalog(context).GetType(context, SYSTEM_CATALOG, DEFAULT_SCHEMA, type.GetAlias());
510
+ }
511
+ // Look for LogicalTypeId::USER in nested types
512
+ if (type.id() == LogicalTypeId::STRUCT) {
513
+ child_list_t<LogicalType> children;
514
+ children.reserve(StructType::GetChildCount(type));
515
+ for (auto &child : StructType::GetChildTypes(type)) {
516
+ children.emplace_back(child.first, GetUserTypeRecursive(child.second, context));
517
+ }
518
+ return LogicalType::STRUCT(std::move(children));
519
+ }
520
+ if (type.id() == LogicalTypeId::LIST) {
521
+ return LogicalType::LIST(GetUserTypeRecursive(ListType::GetChildType(type), context));
522
+ }
523
+ if (type.id() == LogicalTypeId::MAP) {
524
+ return LogicalType::MAP(GetUserTypeRecursive(MapType::KeyType(type), context),
525
+ GetUserTypeRecursive(MapType::ValueType(type), context));
526
+ }
527
+ // Not LogicalTypeId::USER or a nested type
528
+ return type;
529
+ }
530
+
507
531
  LogicalType TransformStringToLogicalType(const string &str, ClientContext &context) {
508
- auto type = TransformStringToLogicalType(str);
509
- return type.id() == LogicalTypeId::USER
510
- ? Catalog::GetSystemCatalog(context).GetType(context, SYSTEM_CATALOG, DEFAULT_SCHEMA, str)
511
- : type;
532
+ return GetUserTypeRecursive(TransformStringToLogicalType(str), context);
512
533
  }
513
534
 
514
535
  bool LogicalType::IsIntegral() const {
@@ -888,18 +909,23 @@ void LogicalType::SetAlias(string alias) {
888
909
  }
889
910
 
890
911
  string LogicalType::GetAlias() const {
891
- if (!type_info_) {
892
- return string();
893
- } else {
912
+ if (id() == LogicalTypeId::USER) {
913
+ return UserType::GetTypeName(*this);
914
+ }
915
+ if (type_info_) {
894
916
  return type_info_->alias;
895
917
  }
918
+ return string();
896
919
  }
897
920
 
898
921
  bool LogicalType::HasAlias() const {
899
- if (!type_info_) {
900
- return false;
922
+ if (id() == LogicalTypeId::USER) {
923
+ return !UserType::GetTypeName(*this).empty();
924
+ }
925
+ if (type_info_ && !type_info_->alias.empty()) {
926
+ return true;
901
927
  }
902
- return !type_info_->alias.empty();
928
+ return false;
903
929
  }
904
930
 
905
931
  void LogicalType::SetCatalog(LogicalType &type, TypeCatalogEntry *catalog_entry) {
@@ -65,9 +65,12 @@ void ColumnBindingResolver::VisitOperator(LogicalOperator &op) {
65
65
  // ON CONFLICT DO UPDATE clause
66
66
  auto &insert_op = (LogicalInsert &)op;
67
67
  if (insert_op.action_type != OnConflictAction::THROW) {
68
+ // Get the bindings from the children
68
69
  VisitOperatorChildren(op);
69
- auto dummy_bindings = LogicalOperator::GenerateColumnBindings(
70
- insert_op.excluded_table_index, insert_op.table->GetColumns().PhysicalColumnCount());
70
+ auto column_count = insert_op.table->GetColumns().PhysicalColumnCount();
71
+ auto dummy_bindings = LogicalOperator::GenerateColumnBindings(insert_op.excluded_table_index, column_count);
72
+ // Now insert our dummy bindings at the start of the bindings,
73
+ // so the first 'column_count' indices of the chunk are reserved for our 'excluded' columns
71
74
  bindings.insert(bindings.begin(), dummy_bindings.begin(), dummy_bindings.end());
72
75
  if (insert_op.on_conflict_condition) {
73
76
  VisitExpression(&insert_op.on_conflict_condition);
@@ -664,6 +664,7 @@ public:
664
664
  if (!matches[outer_idx]) {
665
665
  true_sel.set_index(count++, outer_idx);
666
666
  if (count >= STANDARD_VECTOR_SIZE) {
667
+ outer_idx++;
667
668
  break;
668
669
  }
669
670
  }
@@ -847,8 +848,6 @@ public:
847
848
 
848
849
  lstate.joiner = make_unique<IEJoinUnion>(client, op, left_table, b1, right_table, b2);
849
850
  return;
850
- } else {
851
- --next_pair;
852
851
  }
853
852
 
854
853
  // Outer joins
@@ -864,6 +863,7 @@ public:
864
863
  // Left outer blocks
865
864
  const auto l = next_left++;
866
865
  if (l < left_outers) {
866
+ lstate.joiner = nullptr;
867
867
  lstate.left_block_index = l;
868
868
  lstate.left_base = left_bases[l];
869
869
 
@@ -873,12 +873,12 @@ public:
873
873
  return;
874
874
  } else {
875
875
  lstate.left_matches = nullptr;
876
- --next_left;
877
876
  }
878
877
 
879
878
  // Right outer block
880
879
  const auto r = next_right++;
881
880
  if (r < right_outers) {
881
+ lstate.joiner = nullptr;
882
882
  lstate.right_block_index = r;
883
883
  lstate.right_base = right_bases[r];
884
884
 
@@ -888,7 +888,6 @@ public:
888
888
  return;
889
889
  } else {
890
890
  lstate.right_matches = nullptr;
891
- --next_right;
892
891
  }
893
892
  }
894
893
 
@@ -936,7 +935,7 @@ void PhysicalIEJoin::GetData(ExecutionContext &context, DataChunk &result, Globa
936
935
 
937
936
  ie_gstate.Initialize(ie_sink);
938
937
 
939
- if (!ie_lstate.joiner) {
938
+ if (!ie_lstate.joiner && !ie_lstate.left_matches && !ie_lstate.right_matches) {
940
939
  ie_gstate.GetNextPair(context.client, ie_sink, ie_lstate);
941
940
  }
942
941
 
@@ -959,8 +958,7 @@ void PhysicalIEJoin::GetData(ExecutionContext &context, DataChunk &result, Globa
959
958
  ie_gstate.GetNextPair(context.client, ie_sink, ie_lstate);
960
959
  continue;
961
960
  }
962
-
963
- SliceSortedPayload(result, ie_sink.tables[0]->global_sort_state, ie_lstate.left_base, ie_lstate.true_sel,
961
+ SliceSortedPayload(result, ie_sink.tables[0]->global_sort_state, ie_lstate.left_block_index, ie_lstate.true_sel,
964
962
  count);
965
963
 
966
964
  // Fill in NULLs to the right
@@ -983,8 +981,8 @@ void PhysicalIEJoin::GetData(ExecutionContext &context, DataChunk &result, Globa
983
981
  continue;
984
982
  }
985
983
 
986
- SliceSortedPayload(result, ie_sink.tables[1]->global_sort_state, ie_lstate.right_base, ie_lstate.true_sel,
987
- count, left_cols);
984
+ SliceSortedPayload(result, ie_sink.tables[1]->global_sort_state, ie_lstate.right_block_index,
985
+ ie_lstate.true_sel, count, left_cols);
988
986
 
989
987
  // Fill in NULLs to the left
990
988
  for (idx_t col_idx = 0; col_idx < left_cols; ++col_idx) {
@@ -30,15 +30,10 @@ string BaseCSVReader::GetLineNumberStr(idx_t linenr, bool linenr_estimated) {
30
30
  return to_string(linenr + 1) + estimated;
31
31
  }
32
32
 
33
- BaseCSVReader::BaseCSVReader(FileSystem &fs_p, Allocator &allocator, FileOpener *opener_p,
34
- BufferedCSVReaderOptions options_p, const vector<LogicalType> &requested_types)
35
- : fs(fs_p), allocator(allocator), opener(opener_p), options(std::move(options_p)) {
36
- }
37
-
38
- BaseCSVReader::BaseCSVReader(ClientContext &context, BufferedCSVReaderOptions options_p,
33
+ BaseCSVReader::BaseCSVReader(ClientContext &context_p, BufferedCSVReaderOptions options_p,
39
34
  const vector<LogicalType> &requested_types)
40
- : BaseCSVReader(FileSystem::GetFileSystem(context), Allocator::Get(context), FileSystem::GetFileOpener(context),
41
- std::move(options_p), requested_types) {
35
+ : context(context_p), fs(FileSystem::GetFileSystem(context)), allocator(Allocator::Get(context)),
36
+ opener(FileSystem::GetFileOpener(context)), options(std::move(options_p)) {
42
37
  }
43
38
 
44
39
  BaseCSVReader::~BaseCSVReader() {
@@ -144,7 +139,7 @@ bool BaseCSVReader::TryCastValue(const Value &value, const LogicalType &sql_type
144
139
  } else {
145
140
  Value new_value;
146
141
  string error_message;
147
- return value.DefaultTryCastAs(sql_type, new_value, &error_message, true);
142
+ return value.TryCastAs(context, sql_type, new_value, &error_message, true);
148
143
  }
149
144
  }
150
145
 
@@ -481,8 +476,8 @@ bool BaseCSVReader::Flush(DataChunk &insert_chunk, bool try_add_line) {
481
476
  error_message, return_types[col_idx]);
482
477
  } else {
483
478
  // target type is not varchar: perform a cast
484
- success = VectorOperations::DefaultTryCast(parse_chunk.data[col_idx], insert_chunk.data[insert_idx],
485
- parse_chunk.size(), &error_message);
479
+ success = VectorOperations::TryCast(context, parse_chunk.data[col_idx], insert_chunk.data[insert_idx],
480
+ parse_chunk.size(), &error_message);
486
481
  }
487
482
  if (success) {
488
483
  continue;
@@ -23,25 +23,16 @@
23
23
 
24
24
  namespace duckdb {
25
25
 
26
- BufferedCSVReader::BufferedCSVReader(FileSystem &fs_p, Allocator &allocator, FileOpener *opener_p,
27
- BufferedCSVReaderOptions options_p, const vector<LogicalType> &requested_types)
28
- : BaseCSVReader(fs_p, allocator, opener_p, std::move(options_p), requested_types), buffer_size(0), position(0),
29
- start(0) {
30
- file_handle = OpenCSV(options);
31
- Initialize(requested_types);
32
- }
33
-
34
26
  BufferedCSVReader::BufferedCSVReader(ClientContext &context, BufferedCSVReaderOptions options_p,
35
27
  const vector<LogicalType> &requested_types)
36
- : BufferedCSVReader(FileSystem::GetFileSystem(context), Allocator::Get(context), FileSystem::GetFileOpener(context),
37
- std::move(options_p), requested_types) {
28
+ : BaseCSVReader(context, std::move(options_p), requested_types), buffer_size(0), position(0), start(0) {
29
+ file_handle = OpenCSV(options);
30
+ Initialize(requested_types);
38
31
  }
39
32
 
40
33
  BufferedCSVReader::BufferedCSVReader(ClientContext &context, string filename, BufferedCSVReaderOptions options_p,
41
34
  const vector<LogicalType> &requested_types)
42
- : BaseCSVReader(FileSystem::GetFileSystem(context), Allocator::Get(context), FileSystem::GetFileOpener(context),
43
- std::move(options_p), requested_types),
44
- buffer_size(0), position(0), start(0) {
35
+ : BaseCSVReader(context, std::move(options_p), requested_types), buffer_size(0), position(0), start(0) {
45
36
  options.file_path = std::move(filename);
46
37
  file_handle = OpenCSV(options);
47
38
  Initialize(requested_types);
@@ -730,6 +721,9 @@ void BufferedCSVReader::DetectHeader(const vector<vector<LogicalType>> &best_sql
730
721
  names.push_back(column_name);
731
722
  }
732
723
  }
724
+ for (idx_t i = 0; i < MinValue<idx_t>(names.size(), options.name_list.size()); i++) {
725
+ names[i] = options.name_list[i];
726
+ }
733
727
  }
734
728
 
735
729
  vector<LogicalType> BufferedCSVReader::RefineTypeDetection(const vector<LogicalType> &type_candidates,
@@ -899,6 +893,12 @@ vector<LogicalType> BufferedCSVReader::SniffCSV(const vector<LogicalType> &reque
899
893
  DetectCandidateTypes(type_candidates, format_template_candidates, info_candidates, original_options, best_num_cols,
900
894
  best_sql_types_candidates, best_format_candidates, best_header_row);
901
895
 
896
+ if (best_format_candidates.empty() || best_header_row.size() == 0) {
897
+ throw InvalidInputException(
898
+ "Error in file \"%s\": CSV options could not be auto-detected. Consider setting parser options manually.",
899
+ original_options.file_path);
900
+ }
901
+
902
902
  // #######
903
903
  // ### header detection
904
904
  // #######
@@ -60,7 +60,7 @@ bool ParallelCSVReader::SetPosition(DataChunk &insert_chunk) {
60
60
  verification_positions.end_of_last_line = position_buffer;
61
61
  // First buffer doesn't need any setting
62
62
  // Unless we have a header
63
- if (options.header && options.auto_detect) {
63
+ if (options.header) {
64
64
  for (; position_buffer < end_buffer; position_buffer++) {
65
65
  if (StringUtil::CharacterIsNewline((*buffer)[position_buffer])) {
66
66
  bool carrier_return = (*buffer)[position_buffer] == '\r';
@@ -0,0 +1,37 @@
1
+ #include "duckdb/execution/operator/schema/physical_detach.hpp"
2
+ #include "duckdb/parser/parsed_data/detach_info.hpp"
3
+ #include "duckdb/catalog/catalog.hpp"
4
+ #include "duckdb/main/database_manager.hpp"
5
+ #include "duckdb/main/attached_database.hpp"
6
+ #include "duckdb/main/database.hpp"
7
+ #include "duckdb/storage/storage_extension.hpp"
8
+
9
+ namespace duckdb {
10
+
11
+ //===--------------------------------------------------------------------===//
12
+ // Source
13
+ //===--------------------------------------------------------------------===//
14
+ class DetachSourceState : public GlobalSourceState {
15
+ public:
16
+ DetachSourceState() : finished(false) {
17
+ }
18
+
19
+ bool finished;
20
+ };
21
+
22
+ unique_ptr<GlobalSourceState> PhysicalDetach::GetGlobalSourceState(ClientContext &context) const {
23
+ return make_unique<DetachSourceState>();
24
+ }
25
+
26
+ void PhysicalDetach::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate,
27
+ LocalSourceState &lstate) const {
28
+ auto &state = (DetachSourceState &)gstate;
29
+ if (state.finished) {
30
+ return;
31
+ }
32
+ auto &db_manager = DatabaseManager::Get(context.client);
33
+ db_manager.DetachDatabase(context.client, info->name, info->if_exists);
34
+ state.finished = true;
35
+ }
36
+
37
+ } // namespace duckdb
@@ -38,11 +38,6 @@ void PhysicalDrop::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSo
38
38
  }
39
39
  break;
40
40
  }
41
- case CatalogType::DATABASE_ENTRY: {
42
- auto &db_manager = DatabaseManager::Get(context.client);
43
- db_manager.DetachDatabase(context.client, info->name, info->if_exists);
44
- break;
45
- }
46
41
  case CatalogType::SCHEMA_ENTRY: {
47
42
  auto &catalog = Catalog::GetCatalog(context.client, info->catalog);
48
43
  catalog.DropEntry(context.client, info.get());
@@ -6,6 +6,7 @@
6
6
  #include "duckdb/execution/operator/schema/physical_create_schema.hpp"
7
7
  #include "duckdb/execution/operator/schema/physical_create_sequence.hpp"
8
8
  #include "duckdb/execution/operator/schema/physical_create_view.hpp"
9
+ #include "duckdb/execution/operator/schema/physical_detach.hpp"
9
10
  #include "duckdb/execution/operator/schema/physical_drop.hpp"
10
11
  #include "duckdb/execution/physical_plan_generator.hpp"
11
12
  #include "duckdb/planner/logical_operator.hpp"
@@ -39,6 +40,9 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalSimple &op
39
40
  case LogicalOperatorType::LOGICAL_ATTACH:
40
41
  return make_unique<PhysicalAttach>(unique_ptr_cast<ParseInfo, AttachInfo>(std::move(op.info)),
41
42
  op.estimated_cardinality);
43
+ case LogicalOperatorType::LOGICAL_DETACH:
44
+ return make_unique<PhysicalDetach>(unique_ptr_cast<ParseInfo, DetachInfo>(std::move(op.info)),
45
+ op.estimated_cardinality);
42
46
  default:
43
47
  throw NotImplementedException("Unimplemented type for logical simple operator");
44
48
  }
@@ -184,6 +184,7 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalOperator &
184
184
  case LogicalOperatorType::LOGICAL_VACUUM:
185
185
  case LogicalOperatorType::LOGICAL_LOAD:
186
186
  case LogicalOperatorType::LOGICAL_ATTACH:
187
+ case LogicalOperatorType::LOGICAL_DETACH:
187
188
  plan = CreatePlan((LogicalSimple &)op);
188
189
  break;
189
190
  case LogicalOperatorType::LOGICAL_RECURSIVE_CTE:
@@ -1,10 +1,12 @@
1
- #include "duckdb/function/pragma/pragma_functions.hpp"
2
- #include "duckdb/common/string_util.hpp"
1
+ #include "duckdb/common/constants.hpp"
3
2
  #include "duckdb/common/file_system.hpp"
4
- #include "duckdb/parser/statement/export_statement.hpp"
5
- #include "duckdb/parser/statement/copy_statement.hpp"
6
- #include "duckdb/parser/parser.hpp"
3
+ #include "duckdb/common/string_util.hpp"
4
+ #include "duckdb/function/pragma/pragma_functions.hpp"
7
5
  #include "duckdb/main/config.hpp"
6
+ #include "duckdb/parser/parser.hpp"
7
+ #include "duckdb/parser/qualified_name.hpp"
8
+ #include "duckdb/parser/statement/copy_statement.hpp"
9
+ #include "duckdb/parser/statement/export_statement.hpp"
8
10
 
9
11
  namespace duckdb {
10
12
 
@@ -58,10 +60,35 @@ string PragmaFunctionsQuery(ClientContext &context, const FunctionParameters &pa
58
60
 
59
61
  string PragmaShow(ClientContext &context, const FunctionParameters &parameters) {
60
62
  // PRAGMA table_info but with some aliases
61
- return StringUtil::Format(
62
- "SELECT name AS \"column_name\", type as \"column_type\", CASE WHEN \"notnull\" THEN 'NO' ELSE 'YES' "
63
- "END AS \"null\", NULL AS \"key\", dflt_value AS \"default\", NULL AS \"extra\" FROM pragma_table_info('%s');",
64
- parameters.values[0].ToString());
63
+ auto table = QualifiedName::Parse(parameters.values[0].ToString());
64
+
65
+ // clang-format off
66
+ string sql = R"(
67
+ SELECT
68
+ name AS "column_name",
69
+ type as "column_type",
70
+ CASE WHEN "notnull" THEN 'NO' ELSE 'YES' END AS "null",
71
+ (SELECT
72
+ MIN(CASE
73
+ WHEN constraint_type='PRIMARY KEY' THEN 'PRI'
74
+ WHEN constraint_type='UNIQUE' THEN 'UNI'
75
+ ELSE NULL END)
76
+ FROM duckdb_constraints() c
77
+ WHERE c.table_oid=cols.table_oid
78
+ AND list_contains(constraint_column_names, cols.column_name)) AS "key",
79
+ dflt_value AS "default",
80
+ NULL AS "extra"
81
+ FROM pragma_table_info('%func_param_table%')
82
+ LEFT JOIN duckdb_columns cols
83
+ ON cols.column_name = pragma_table_info.name
84
+ AND cols.table_name='%table_name%'
85
+ AND cols.schema_name='%table_schema%';)";
86
+ // clang-format on
87
+
88
+ sql = StringUtil::Replace(sql, "%func_param_table%", parameters.values[0].ToString());
89
+ sql = StringUtil::Replace(sql, "%table_name%", table.name);
90
+ sql = StringUtil::Replace(sql, "%table_schema%", table.schema.empty() ? DEFAULT_SCHEMA : table.schema);
91
+ return sql;
65
92
  }
66
93
 
67
94
  string PragmaVersion(ClientContext &context, const FunctionParameters &parameters) {
@@ -10,6 +10,7 @@
10
10
  #include "duckdb/parser/expression/function_expression.hpp"
11
11
  #include "duckdb/parser/tableref/table_function_ref.hpp"
12
12
  #include "duckdb/planner/operator/logical_get.hpp"
13
+ #include "duckdb/main/extension_helper.hpp"
13
14
 
14
15
  #include <limits>
15
16
 
@@ -29,7 +30,7 @@ void ReadCSVData::InitializeFiles(ClientContext &context, const vector<string> &
29
30
  for (auto &file_pattern : patterns) {
30
31
  auto found_files = fs.Glob(file_pattern, context);
31
32
  if (found_files.empty()) {
32
- throw IOException("No files found that match the pattern \"%s\"", file_pattern);
33
+ throw FileSystem::MissingFileException(file_pattern, context);
33
34
  }
34
35
  files.insert(files.end(), found_files.begin(), found_files.end());
35
36
  }
@@ -98,6 +99,17 @@ static unique_ptr<FunctionData> ReadCSVBind(ClientContext &context, TableFunctio
98
99
  if (names.empty()) {
99
100
  throw BinderException("read_csv requires at least a single column as input!");
100
101
  }
102
+ } else if (loption == "column_names" || loption == "names") {
103
+ if (!options.name_list.empty()) {
104
+ throw BinderException("read_csv_auto column_names/names can only be supplied once");
105
+ }
106
+ if (kv.second.IsNull()) {
107
+ throw BinderException("read_csv_auto %s cannot be NULL", kv.first);
108
+ }
109
+ auto &children = ListValue::GetChildren(kv.second);
110
+ for (auto &child : children) {
111
+ options.name_list.push_back(StringValue::Get(child));
112
+ }
101
113
  } else if (loption == "column_types" || loption == "types" || loption == "dtypes") {
102
114
  auto &child_type = kv.second.type();
103
115
  if (child_type.id() != LogicalTypeId::STRUCT && child_type.id() != LogicalTypeId::LIST) {
@@ -251,9 +263,6 @@ public:
251
263
  : file_handle(std::move(file_handle_p)), system_threads(system_threads_p), buffer_size(buffer_size_p),
252
264
  force_parallelism(force_parallelism_p) {
253
265
  current_file_path = files_path_p[0];
254
- for (idx_t i = 0; i < rows_to_skip; i++) {
255
- file_handle->ReadLine();
256
- }
257
266
  estimated_linenr = rows_to_skip;
258
267
  file_size = file_handle->FileSize();
259
268
  first_file_size = file_size;
@@ -963,6 +972,8 @@ TableFunction ReadCSVTableFunction::GetAutoFunction(bool list_parameter) {
963
972
  read_csv_auto.named_parameters["column_types"] = LogicalType::ANY;
964
973
  read_csv_auto.named_parameters["dtypes"] = LogicalType::ANY;
965
974
  read_csv_auto.named_parameters["types"] = LogicalType::ANY;
975
+ read_csv_auto.named_parameters["names"] = LogicalType::LIST(LogicalType::VARCHAR);
976
+ read_csv_auto.named_parameters["column_names"] = LogicalType::LIST(LogicalType::VARCHAR);
966
977
  return read_csv_auto;
967
978
  }
968
979
 
@@ -1,8 +1,8 @@
1
1
  #ifndef DUCKDB_VERSION
2
- #define DUCKDB_VERSION "0.7.1-dev19"
2
+ #define DUCKDB_VERSION "0.7.1-dev240"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "380f2ab86b"
5
+ #define DUCKDB_SOURCE_ID "661b09da10"
6
6
  #endif
7
7
  #include "duckdb/function/table/system_functions.hpp"
8
8
  #include "duckdb/main/database.hpp"