duckdb 0.7.1-dev37.0 → 0.7.1-dev407.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 (166) hide show
  1. package/README.md +1 -1
  2. package/binding.gyp +7 -7
  3. package/package.json +3 -3
  4. package/src/duckdb/extension/json/buffered_json_reader.cpp +50 -9
  5. package/src/duckdb/extension/json/include/buffered_json_reader.hpp +7 -2
  6. package/src/duckdb/extension/json/include/json_scan.hpp +45 -10
  7. package/src/duckdb/extension/json/json_functions/copy_json.cpp +35 -22
  8. package/src/duckdb/extension/json/json_functions/json_create.cpp +8 -8
  9. package/src/duckdb/extension/json/json_functions/json_structure.cpp +8 -3
  10. package/src/duckdb/extension/json/json_functions/json_transform.cpp +54 -10
  11. package/src/duckdb/extension/json/json_functions/read_json.cpp +104 -49
  12. package/src/duckdb/extension/json/json_functions/read_json_objects.cpp +5 -3
  13. package/src/duckdb/extension/json/json_functions.cpp +7 -0
  14. package/src/duckdb/extension/json/json_scan.cpp +144 -37
  15. package/src/duckdb/extension/parquet/column_reader.cpp +7 -0
  16. package/src/duckdb/extension/parquet/include/column_reader.hpp +1 -0
  17. package/src/duckdb/extension/parquet/parquet-extension.cpp +2 -9
  18. package/src/duckdb/src/catalog/catalog.cpp +62 -13
  19. package/src/duckdb/src/catalog/catalog_entry/index_catalog_entry.cpp +8 -7
  20. package/src/duckdb/src/catalog/default/default_views.cpp +1 -1
  21. package/src/duckdb/src/common/bind_helpers.cpp +55 -0
  22. package/src/duckdb/src/common/enums/logical_operator_type.cpp +2 -0
  23. package/src/duckdb/src/common/enums/physical_operator_type.cpp +2 -0
  24. package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
  25. package/src/duckdb/src/common/file_system.cpp +28 -0
  26. package/src/duckdb/src/common/hive_partitioning.cpp +1 -0
  27. package/src/duckdb/src/common/local_file_system.cpp +4 -4
  28. package/src/duckdb/src/common/operator/cast_operators.cpp +10 -4
  29. package/src/duckdb/src/common/types/partitioned_column_data.cpp +1 -0
  30. package/src/duckdb/src/common/types/time.cpp +1 -1
  31. package/src/duckdb/src/common/types/timestamp.cpp +35 -4
  32. package/src/duckdb/src/common/types.cpp +37 -11
  33. package/src/duckdb/src/execution/column_binding_resolver.cpp +5 -2
  34. package/src/duckdb/src/execution/index/art/art.cpp +117 -67
  35. package/src/duckdb/src/execution/index/art/art_key.cpp +24 -12
  36. package/src/duckdb/src/execution/index/art/leaf.cpp +7 -8
  37. package/src/duckdb/src/execution/index/art/node.cpp +13 -27
  38. package/src/duckdb/src/execution/index/art/node16.cpp +5 -8
  39. package/src/duckdb/src/execution/index/art/node256.cpp +3 -5
  40. package/src/duckdb/src/execution/index/art/node4.cpp +4 -7
  41. package/src/duckdb/src/execution/index/art/node48.cpp +5 -8
  42. package/src/duckdb/src/execution/index/art/prefix.cpp +2 -3
  43. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +6 -27
  44. package/src/duckdb/src/execution/operator/helper/physical_reset.cpp +1 -9
  45. package/src/duckdb/src/execution/operator/helper/physical_set.cpp +1 -9
  46. package/src/duckdb/src/execution/operator/join/physical_iejoin.cpp +7 -9
  47. package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +6 -11
  48. package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +13 -13
  49. package/src/duckdb/src/execution/operator/schema/physical_detach.cpp +37 -0
  50. package/src/duckdb/src/execution/operator/schema/physical_drop.cpp +0 -5
  51. package/src/duckdb/src/execution/physical_operator.cpp +6 -6
  52. package/src/duckdb/src/execution/physical_plan/plan_simple.cpp +4 -0
  53. package/src/duckdb/src/execution/physical_plan_generator.cpp +1 -0
  54. package/src/duckdb/src/function/pragma/pragma_queries.cpp +38 -11
  55. package/src/duckdb/src/function/scalar/generic/current_setting.cpp +2 -2
  56. package/src/duckdb/src/function/scalar/map/map.cpp +69 -21
  57. package/src/duckdb/src/function/table/read_csv.cpp +17 -5
  58. package/src/duckdb/src/function/table/system/duckdb_temporary_files.cpp +59 -0
  59. package/src/duckdb/src/function/table/system_functions.cpp +1 -0
  60. package/src/duckdb/src/function/table/table_scan.cpp +3 -0
  61. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  62. package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +7 -1
  63. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp +1 -1
  64. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/index_catalog_entry.hpp +1 -1
  65. package/src/duckdb/src/include/duckdb/common/bind_helpers.hpp +2 -0
  66. package/src/duckdb/src/include/duckdb/common/enums/logical_operator_type.hpp +1 -0
  67. package/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp +1 -0
  68. package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +3 -2
  69. package/src/duckdb/src/include/duckdb/common/enums/wal_type.hpp +3 -0
  70. package/src/duckdb/src/include/duckdb/common/exception.hpp +10 -0
  71. package/src/duckdb/src/include/duckdb/common/file_system.hpp +1 -0
  72. package/src/duckdb/src/include/duckdb/common/hive_partitioning.hpp +9 -1
  73. package/src/duckdb/src/include/duckdb/common/radix_partitioning.hpp +4 -4
  74. package/src/duckdb/src/include/duckdb/common/types/timestamp.hpp +5 -1
  75. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +37 -41
  76. package/src/duckdb/src/include/duckdb/execution/index/art/art_key.hpp +8 -11
  77. package/src/duckdb/src/include/duckdb/execution/operator/persistent/base_csv_reader.hpp +1 -3
  78. package/src/duckdb/src/include/duckdb/execution/operator/persistent/buffered_csv_reader.hpp +0 -2
  79. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +2 -0
  80. package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_detach.hpp +32 -0
  81. package/src/duckdb/src/include/duckdb/function/table/system_functions.hpp +4 -0
  82. package/src/duckdb/src/include/duckdb/main/client_data.hpp +2 -2
  83. package/src/duckdb/src/include/duckdb/main/config.hpp +2 -3
  84. package/src/duckdb/src/include/duckdb/main/{extension_functions.hpp → extension_entries.hpp} +26 -5
  85. package/src/duckdb/src/include/duckdb/main/extension_helper.hpp +3 -0
  86. package/src/duckdb/src/include/duckdb/main/settings.hpp +9 -0
  87. package/src/duckdb/src/include/duckdb/parallel/pipeline_executor.hpp +0 -7
  88. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_database_info.hpp +0 -4
  89. package/src/duckdb/src/include/duckdb/parser/parsed_data/detach_info.hpp +32 -0
  90. package/src/duckdb/src/include/duckdb/parser/query_node/select_node.hpp +1 -1
  91. package/src/duckdb/src/include/duckdb/parser/sql_statement.hpp +2 -2
  92. package/src/duckdb/src/include/duckdb/parser/statement/copy_statement.hpp +1 -1
  93. package/src/duckdb/src/include/duckdb/parser/statement/detach_statement.hpp +29 -0
  94. package/src/duckdb/src/include/duckdb/parser/statement/list.hpp +1 -0
  95. package/src/duckdb/src/include/duckdb/parser/statement/select_statement.hpp +3 -3
  96. package/src/duckdb/src/include/duckdb/parser/tableref/subqueryref.hpp +1 -1
  97. package/src/duckdb/src/include/duckdb/parser/tokens.hpp +1 -0
  98. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +1 -0
  99. package/src/duckdb/src/include/duckdb/planner/binder.hpp +4 -0
  100. package/src/duckdb/src/include/duckdb/planner/expression_binder/index_binder.hpp +10 -3
  101. package/src/duckdb/src/include/duckdb/planner/operator/logical_execute.hpp +1 -5
  102. package/src/duckdb/src/include/duckdb/planner/operator/logical_show.hpp +1 -2
  103. package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +8 -0
  104. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +7 -1
  105. package/src/duckdb/src/include/duckdb/storage/index.hpp +47 -38
  106. package/src/duckdb/src/include/duckdb/storage/storage_extension.hpp +7 -0
  107. package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +2 -0
  108. package/src/duckdb/src/include/duckdb/storage/write_ahead_log.hpp +7 -0
  109. package/src/duckdb/src/main/client_context.cpp +2 -0
  110. package/src/duckdb/src/main/config.cpp +1 -0
  111. package/src/duckdb/src/main/database.cpp +14 -5
  112. package/src/duckdb/src/main/extension/extension_alias.cpp +2 -1
  113. package/src/duckdb/src/main/extension/extension_install.cpp +43 -9
  114. package/src/duckdb/src/main/extension/extension_load.cpp +29 -5
  115. package/src/duckdb/src/main/settings/settings.cpp +16 -0
  116. package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +2 -6
  117. package/src/duckdb/src/parallel/pipeline_executor.cpp +1 -55
  118. package/src/duckdb/src/parser/parsed_data/create_index_info.cpp +3 -0
  119. package/src/duckdb/src/parser/statement/copy_statement.cpp +2 -13
  120. package/src/duckdb/src/parser/statement/delete_statement.cpp +3 -0
  121. package/src/duckdb/src/parser/statement/detach_statement.cpp +15 -0
  122. package/src/duckdb/src/parser/statement/insert_statement.cpp +9 -0
  123. package/src/duckdb/src/parser/statement/update_statement.cpp +3 -0
  124. package/src/duckdb/src/parser/transform/expression/transform_case.cpp +3 -3
  125. package/src/duckdb/src/parser/transform/statement/transform_create_database.cpp +0 -1
  126. package/src/duckdb/src/parser/transform/statement/transform_detach.cpp +19 -0
  127. package/src/duckdb/src/parser/transformer.cpp +2 -0
  128. package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +3 -0
  129. package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +7 -14
  130. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +16 -14
  131. package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +13 -0
  132. package/src/duckdb/src/planner/binder/statement/bind_detach.cpp +19 -0
  133. package/src/duckdb/src/planner/binder/statement/bind_drop.cpp +29 -4
  134. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +22 -1
  135. package/src/duckdb/src/planner/binder.cpp +2 -0
  136. package/src/duckdb/src/planner/expression_binder/index_binder.cpp +32 -1
  137. package/src/duckdb/src/planner/logical_operator.cpp +4 -0
  138. package/src/duckdb/src/planner/planner.cpp +1 -0
  139. package/src/duckdb/src/storage/buffer_manager.cpp +105 -26
  140. package/src/duckdb/src/storage/compression/bitpacking.cpp +16 -7
  141. package/src/duckdb/src/storage/data_table.cpp +66 -3
  142. package/src/duckdb/src/storage/index.cpp +1 -1
  143. package/src/duckdb/src/storage/local_storage.cpp +1 -1
  144. package/src/duckdb/src/storage/table/column_data.cpp +4 -2
  145. package/src/duckdb/src/storage/table/update_segment.cpp +15 -0
  146. package/src/duckdb/src/storage/table_index_list.cpp +1 -2
  147. package/src/duckdb/src/storage/wal_replay.cpp +68 -0
  148. package/src/duckdb/src/storage/write_ahead_log.cpp +21 -1
  149. package/src/duckdb/src/transaction/commit_state.cpp +5 -2
  150. package/src/duckdb/third_party/concurrentqueue/blockingconcurrentqueue.h +2 -2
  151. package/src/duckdb/third_party/fmt/include/fmt/core.h +1 -2
  152. package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +1 -0
  153. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +14 -0
  154. package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +530 -1006
  155. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +17659 -17626
  156. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +4 -4
  157. package/src/duckdb/ub_src_execution_operator_schema.cpp +2 -0
  158. package/src/duckdb/ub_src_function_table_system.cpp +2 -0
  159. package/src/duckdb/ub_src_parser_statement.cpp +2 -0
  160. package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
  161. package/src/duckdb/ub_src_planner_binder_statement.cpp +2 -0
  162. package/src/statement.cpp +46 -12
  163. package/test/arrow.test.ts +3 -3
  164. package/test/prepare.test.ts +39 -1
  165. package/test/typescript_decls.test.ts +1 -1
  166. package/src/duckdb/src/include/duckdb/function/create_database_extension.hpp +0 -37
@@ -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
  }
@@ -10,6 +10,7 @@
10
10
  #include "duckdb/main/client_context.hpp"
11
11
  #include "duckdb/main/client_data.hpp"
12
12
  #include "duckdb/main/database.hpp"
13
+ #include "duckdb/main/extension_helper.hpp"
13
14
 
14
15
  #include <cstdint>
15
16
  #include <cstdio>
@@ -335,6 +336,33 @@ bool FileSystem::CanHandleFile(const string &fpath) {
335
336
  throw NotImplementedException("%s: CanHandleFile is not implemented!", GetName());
336
337
  }
337
338
 
339
+ vector<string> FileSystem::GlobFiles(const string &pattern, ClientContext &context) {
340
+ auto result = Glob(pattern, context);
341
+ if (result.empty()) {
342
+ string required_extension;
343
+ const string prefixes[] = {"http://", "https://", "s3://"};
344
+ for (auto &prefix : prefixes) {
345
+ if (StringUtil::StartsWith(pattern, prefix)) {
346
+ required_extension = "httpfs";
347
+ break;
348
+ }
349
+ }
350
+ if (!required_extension.empty() && !context.db->ExtensionIsLoaded(required_extension)) {
351
+ // an extension is required to read this file but it is not loaded - try to load it
352
+ ExtensionHelper::LoadExternalExtension(context, required_extension);
353
+ // success! glob again
354
+ // check the extension is loaded just in case to prevent an infinite loop here
355
+ if (!context.db->ExtensionIsLoaded(required_extension)) {
356
+ throw InternalException("Extension load \"%s\" did not throw but somehow the extension was not loaded",
357
+ required_extension);
358
+ }
359
+ return GlobFiles(pattern, context);
360
+ }
361
+ throw IOException("No files found that match the pattern \"%s\"", pattern);
362
+ }
363
+ return result;
364
+ }
365
+
338
366
  void FileSystem::Seek(FileHandle &handle, idx_t location) {
339
367
  throw NotImplementedException("%s: Seek is not implemented!", GetName());
340
368
  }
@@ -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;
@@ -833,8 +833,8 @@ static bool HasGlob(const string &str) {
833
833
  return false;
834
834
  }
835
835
 
836
- static void GlobFiles(FileSystem &fs, const string &path, const string &glob, bool match_directory,
837
- vector<string> &result, bool join_path) {
836
+ static void GlobFilesInternal(FileSystem &fs, const string &path, const string &glob, bool match_directory,
837
+ vector<string> &result, bool join_path) {
838
838
  fs.ListFiles(path, [&](const string &fname, bool is_directory) {
839
839
  if (is_directory != match_directory) {
840
840
  return;
@@ -951,12 +951,12 @@ vector<string> LocalFileSystem::Glob(const string &path, FileOpener *opener) {
951
951
  } else {
952
952
  if (previous_directories.empty()) {
953
953
  // no previous directories: list in the current path
954
- GlobFiles(*this, ".", splits[i], !is_last_chunk, result, false);
954
+ GlobFilesInternal(*this, ".", splits[i], !is_last_chunk, result, false);
955
955
  } else {
956
956
  // previous directories
957
957
  // we iterate over each of the previous directories, and apply the glob of the current directory
958
958
  for (auto &prev_directory : previous_directories) {
959
- GlobFiles(*this, prev_directory, splits[i], !is_last_chunk, result, true);
959
+ GlobFilesInternal(*this, prev_directory, splits[i], !is_last_chunk, result, true);
960
960
  }
961
961
  }
962
962
  }
@@ -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 <>
@@ -137,6 +137,7 @@ void PartitionedColumnData::FlushAppendState(PartitionedColumnDataAppendState &s
137
137
  auto &partition_buffer = *state.partition_buffers[i];
138
138
  if (partition_buffer.size() > 0) {
139
139
  partitions[i]->Append(partition_buffer);
140
+ partition_buffer.Reset();
140
141
  }
141
142
  }
142
143
  }
@@ -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) {
@@ -424,7 +424,7 @@ string LogicalType::ToString() const {
424
424
  auto &child_types = StructType::GetChildTypes(*this);
425
425
  string ret = "STRUCT(";
426
426
  for (size_t i = 0; i < child_types.size(); i++) {
427
- ret += child_types[i].first + " " + child_types[i].second.ToString();
427
+ ret += KeywordHelper::WriteOptionallyQuoted(child_types[i].first) + " " + child_types[i].second.ToString();
428
428
  if (i < child_types.size() - 1) {
429
429
  ret += ", ";
430
430
  }
@@ -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);