duckdb 0.7.1-dev11.0 → 0.7.1-dev137.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 (80) hide show
  1. package/package.json +1 -1
  2. package/src/duckdb/extension/json/buffered_json_reader.cpp +29 -5
  3. package/src/duckdb/extension/json/include/buffered_json_reader.hpp +5 -1
  4. package/src/duckdb/extension/json/include/json_scan.hpp +17 -2
  5. package/src/duckdb/extension/json/json_functions/json_transform.cpp +19 -0
  6. package/src/duckdb/extension/json/json_functions/read_json.cpp +30 -28
  7. package/src/duckdb/extension/json/json_functions.cpp +6 -0
  8. package/src/duckdb/extension/json/json_scan.cpp +111 -23
  9. package/src/duckdb/extension/parquet/parquet-extension.cpp +3 -2
  10. package/src/duckdb/src/common/enums/logical_operator_type.cpp +2 -0
  11. package/src/duckdb/src/common/enums/physical_operator_type.cpp +2 -0
  12. package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
  13. package/src/duckdb/src/common/file_system.cpp +14 -0
  14. package/src/duckdb/src/common/operator/cast_operators.cpp +14 -8
  15. package/src/duckdb/src/common/printer.cpp +1 -1
  16. package/src/duckdb/src/common/types/time.cpp +1 -1
  17. package/src/duckdb/src/common/types/timestamp.cpp +35 -4
  18. package/src/duckdb/src/common/types.cpp +36 -10
  19. package/src/duckdb/src/execution/column_binding_resolver.cpp +5 -2
  20. package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +6 -11
  21. package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +7 -13
  22. package/src/duckdb/src/execution/operator/persistent/parallel_csv_reader.cpp +1 -1
  23. package/src/duckdb/src/execution/operator/schema/physical_detach.cpp +37 -0
  24. package/src/duckdb/src/execution/operator/schema/physical_drop.cpp +0 -5
  25. package/src/duckdb/src/execution/physical_plan/plan_simple.cpp +4 -0
  26. package/src/duckdb/src/execution/physical_plan_generator.cpp +1 -0
  27. package/src/duckdb/src/function/pragma/pragma_queries.cpp +36 -9
  28. package/src/duckdb/src/function/table/read_csv.cpp +15 -4
  29. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  30. package/src/duckdb/src/include/duckdb/common/enums/logical_operator_type.hpp +1 -0
  31. package/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp +1 -0
  32. package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +2 -1
  33. package/src/duckdb/src/include/duckdb/common/exception.hpp +10 -0
  34. package/src/duckdb/src/include/duckdb/common/file_system.hpp +1 -0
  35. package/src/duckdb/src/include/duckdb/common/types/timestamp.hpp +5 -1
  36. package/src/duckdb/src/include/duckdb/execution/operator/persistent/base_csv_reader.hpp +1 -3
  37. package/src/duckdb/src/include/duckdb/execution/operator/persistent/buffered_csv_reader.hpp +0 -2
  38. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +2 -0
  39. package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_detach.hpp +32 -0
  40. package/src/duckdb/src/include/duckdb/main/client_data.hpp +2 -2
  41. package/src/duckdb/src/include/duckdb/main/config.hpp +0 -3
  42. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_database_info.hpp +0 -4
  43. package/src/duckdb/src/include/duckdb/parser/parsed_data/detach_info.hpp +32 -0
  44. package/src/duckdb/src/include/duckdb/parser/statement/detach_statement.hpp +29 -0
  45. package/src/duckdb/src/include/duckdb/parser/statement/list.hpp +1 -0
  46. package/src/duckdb/src/include/duckdb/parser/tokens.hpp +1 -0
  47. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +1 -0
  48. package/src/duckdb/src/include/duckdb/planner/binder.hpp +1 -0
  49. package/src/duckdb/src/include/duckdb/planner/operator/logical_execute.hpp +1 -5
  50. package/src/duckdb/src/include/duckdb/planner/operator/logical_show.hpp +1 -2
  51. package/src/duckdb/src/include/duckdb/storage/storage_extension.hpp +7 -0
  52. package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +2 -0
  53. package/src/duckdb/src/parser/statement/copy_statement.cpp +2 -13
  54. package/src/duckdb/src/parser/statement/detach_statement.cpp +15 -0
  55. package/src/duckdb/src/parser/statement/insert_statement.cpp +3 -0
  56. package/src/duckdb/src/parser/transform/expression/transform_case.cpp +3 -3
  57. package/src/duckdb/src/parser/transform/statement/transform_create_database.cpp +0 -1
  58. package/src/duckdb/src/parser/transform/statement/transform_detach.cpp +19 -0
  59. package/src/duckdb/src/parser/transformer.cpp +2 -0
  60. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +16 -14
  61. package/src/duckdb/src/planner/binder/statement/bind_detach.cpp +19 -0
  62. package/src/duckdb/src/planner/binder/statement/bind_drop.cpp +29 -4
  63. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +22 -1
  64. package/src/duckdb/src/planner/binder/tableref/bind_joinref.cpp +2 -1
  65. package/src/duckdb/src/planner/binder.cpp +2 -0
  66. package/src/duckdb/src/planner/expression_binder/lateral_binder.cpp +21 -5
  67. package/src/duckdb/src/planner/logical_operator.cpp +4 -0
  68. package/src/duckdb/src/planner/planner.cpp +1 -0
  69. package/src/duckdb/src/storage/storage_info.cpp +2 -1
  70. package/src/duckdb/src/storage/table/column_data.cpp +4 -2
  71. package/src/duckdb/src/storage/table/update_segment.cpp +15 -0
  72. package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +1 -0
  73. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +14 -0
  74. package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +530 -1006
  75. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +17659 -17626
  76. package/src/duckdb/ub_src_execution_operator_schema.cpp +2 -0
  77. package/src/duckdb/ub_src_parser_statement.cpp +2 -0
  78. package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
  79. package/src/duckdb/ub_src_planner_binder_statement.cpp +2 -0
  80. package/src/duckdb/src/include/duckdb/function/create_database_extension.hpp +0 -37
@@ -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
  }
@@ -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);
@@ -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,
@@ -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-dev11"
2
+ #define DUCKDB_VERSION "0.7.1-dev137"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "14a51626cd"
5
+ #define DUCKDB_SOURCE_ID "eb65c593fe"
6
6
  #endif
7
7
  #include "duckdb/function/table/system_functions.hpp"
8
8
  #include "duckdb/main/database.hpp"
@@ -79,6 +79,7 @@ enum class LogicalOperatorType : uint8_t {
79
79
  LOGICAL_TRANSACTION = 134,
80
80
  LOGICAL_CREATE_TYPE = 135,
81
81
  LOGICAL_ATTACH = 136,
82
+ LOGICAL_DETACH = 137,
82
83
 
83
84
  // -----------------------------
84
85
  // Explain
@@ -87,6 +87,7 @@ enum class PhysicalOperatorType : uint8_t {
87
87
  TRANSACTION,
88
88
  CREATE_TYPE,
89
89
  ATTACH,
90
+ DETACH,
90
91
 
91
92
  // -----------------------------
92
93
  // Helpers
@@ -43,7 +43,8 @@ enum class StatementType : uint8_t {
43
43
  RELATION_STATEMENT,
44
44
  EXTENSION_STATEMENT,
45
45
  LOGICAL_PLAN_STATEMENT,
46
- ATTACH_STATEMENT
46
+ ATTACH_STATEMENT,
47
+ DETACH_STATEMENT
47
48
 
48
49
  };
49
50
 
@@ -262,6 +262,16 @@ public:
262
262
  }
263
263
  };
264
264
 
265
+ class MissingExtensionException : public IOException {
266
+ public:
267
+ DUCKDB_API explicit MissingExtensionException(const string &msg);
268
+
269
+ template <typename... Args>
270
+ explicit MissingExtensionException(const string &msg, Args... params)
271
+ : IOException(ConstructMessage(msg, params...)) {
272
+ }
273
+ };
274
+
265
275
  class SerializationException : public Exception {
266
276
  public:
267
277
  DUCKDB_API explicit SerializationException(const string &msg);
@@ -201,6 +201,7 @@ public:
201
201
 
202
202
  //! Whether or not a sub-system can handle a specific file path
203
203
  DUCKDB_API virtual bool CanHandleFile(const string &fpath);
204
+ DUCKDB_API static IOException MissingFileException(const string &file_path, ClientContext &context);
204
205
 
205
206
  //! Set the file pointer of a file handle to a specified location. Reads and writes will happen from this location
206
207
  DUCKDB_API virtual void Seek(FileHandle &handle, idx_t location);
@@ -93,6 +93,8 @@ struct timestamp_ns_t : public timestamp_t {}; // NOLINT
93
93
  struct timestamp_ms_t : public timestamp_t {}; // NOLINT
94
94
  struct timestamp_sec_t : public timestamp_t {}; // NOLINT
95
95
 
96
+ enum class TimestampCastResult : uint8_t { SUCCESS, ERROR_INCORRECT_FORMAT, ERROR_NON_UTC_TIMEZONE };
97
+
96
98
  //! The Timestamp class is a static class that holds helper functions for the Timestamp
97
99
  //! type.
98
100
  class Timestamp {
@@ -110,7 +112,7 @@ public:
110
112
  //! If the tz is not empty, the result is still an instant, but the parts can be extracted and applied to the TZ
111
113
  DUCKDB_API static bool TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &result, bool &has_offset,
112
114
  string_t &tz);
113
- DUCKDB_API static bool TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result);
115
+ DUCKDB_API static TimestampCastResult TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result);
114
116
  DUCKDB_API static timestamp_t FromCString(const char *str, idx_t len);
115
117
  //! Convert a date object to a string in the format "YYYY-MM-DD hh:mm:ss"
116
118
  DUCKDB_API static string ToString(timestamp_t timestamp);
@@ -161,6 +163,8 @@ public:
161
163
 
162
164
  DUCKDB_API static string ConversionError(const string &str);
163
165
  DUCKDB_API static string ConversionError(string_t str);
166
+ DUCKDB_API static string UnsupportedTimezoneError(const string &str);
167
+ DUCKDB_API static string UnsupportedTimezoneError(string_t str);
164
168
  };
165
169
 
166
170
  } // namespace duckdb
@@ -35,11 +35,9 @@ class BaseCSVReader {
35
35
  public:
36
36
  BaseCSVReader(ClientContext &context, BufferedCSVReaderOptions options,
37
37
  const vector<LogicalType> &requested_types = vector<LogicalType>());
38
-
39
- BaseCSVReader(FileSystem &fs, Allocator &allocator, FileOpener *opener, BufferedCSVReaderOptions options,
40
- const vector<LogicalType> &requested_types = vector<LogicalType>());
41
38
  ~BaseCSVReader();
42
39
 
40
+ ClientContext &context;
43
41
  FileSystem &fs;
44
42
  Allocator &allocator;
45
43
  FileOpener *opener;
@@ -55,8 +55,6 @@ class BufferedCSVReader : public BaseCSVReader {
55
55
  public:
56
56
  BufferedCSVReader(ClientContext &context, BufferedCSVReaderOptions options,
57
57
  const vector<LogicalType> &requested_types = vector<LogicalType>());
58
- BufferedCSVReader(FileSystem &fs, Allocator &allocator, FileOpener *opener, BufferedCSVReaderOptions options,
59
- const vector<LogicalType> &requested_types = vector<LogicalType>());
60
58
  BufferedCSVReader(ClientContext &context, string filename, BufferedCSVReaderOptions options,
61
59
  const vector<LogicalType> &requested_types = vector<LogicalType>());
62
60
  ~BufferedCSVReader();
@@ -75,6 +75,8 @@ struct BufferedCSVReaderOptions {
75
75
  case_insensitive_map_t<idx_t> sql_types_per_column;
76
76
  //! User-defined SQL type list
77
77
  vector<LogicalType> sql_type_list;
78
+ //! User-defined name list
79
+ vector<string> name_list;
78
80
  //===--------------------------------------------------------------------===//
79
81
  // ReadCSVOptions
80
82
  //===--------------------------------------------------------------------===//