duckdb 0.9.1-dev95.0 → 0.9.1

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 (84) hide show
  1. package/.github/workflows/NodeJS.yml +250 -0
  2. package/Makefile +3 -9
  3. package/README.md +2 -2
  4. package/binding.gyp +8 -8
  5. package/package.json +4 -4
  6. package/scripts/install_node.sh +21 -0
  7. package/scripts/node_build.sh +40 -0
  8. package/scripts/node_build_win.sh +21 -0
  9. package/scripts/node_version.sh +33 -0
  10. package/src/duckdb/extension/icu/icu-makedate.cpp +1 -1
  11. package/src/duckdb/extension/icu/icu-strptime.cpp +0 -2
  12. package/src/duckdb/extension/icu/icu_extension.cpp +0 -1
  13. package/src/duckdb/extension/json/json_functions/json_create.cpp +27 -14
  14. package/src/duckdb/extension/json/json_functions/json_transform.cpp +26 -14
  15. package/src/duckdb/extension/json/json_functions.cpp +1 -10
  16. package/src/duckdb/extension/parquet/column_reader.cpp +26 -1
  17. package/src/duckdb/extension/parquet/column_writer.cpp +10 -1
  18. package/src/duckdb/extension/parquet/include/column_reader.hpp +2 -0
  19. package/src/duckdb/extension/parquet/include/parquet_bss_decoder.hpp +49 -0
  20. package/src/duckdb/extension/parquet/parquet_extension.cpp +3 -4
  21. package/src/duckdb/extension/parquet/parquet_timestamp.cpp +3 -4
  22. package/src/duckdb/src/common/arrow/appender/list_data.cpp +2 -2
  23. package/src/duckdb/src/common/arrow/appender/map_data.cpp +15 -10
  24. package/src/duckdb/src/common/arrow/appender/struct_data.cpp +2 -2
  25. package/src/duckdb/src/common/arrow/appender/union_data.cpp +2 -2
  26. package/src/duckdb/src/common/arrow/arrow_appender.cpp +26 -7
  27. package/src/duckdb/src/common/arrow/arrow_wrapper.cpp +3 -3
  28. package/src/duckdb/src/common/exception.cpp +60 -84
  29. package/src/duckdb/src/common/preserved_error.cpp +20 -0
  30. package/src/duckdb/src/common/types/data_chunk.cpp +1 -1
  31. package/src/duckdb/src/execution/expression_executor/execute_reference.cpp +1 -1
  32. package/src/duckdb/src/execution/expression_executor_state.cpp +8 -2
  33. package/src/duckdb/src/execution/operator/csv_scanner/buffered_csv_reader.cpp +1 -1
  34. package/src/duckdb/src/execution/operator/csv_scanner/csv_state_machine_cache.cpp +2 -0
  35. package/src/duckdb/src/execution/operator/csv_scanner/sniffer/csv_sniffer.cpp +5 -5
  36. package/src/duckdb/src/execution/operator/csv_scanner/sniffer/dialect_detection.cpp +4 -4
  37. package/src/duckdb/src/execution/operator/csv_scanner/sniffer/type_replacement.cpp +2 -2
  38. package/src/duckdb/src/execution/operator/helper/physical_reset.cpp +1 -4
  39. package/src/duckdb/src/execution/operator/helper/physical_set.cpp +2 -4
  40. package/src/duckdb/src/execution/perfect_aggregate_hashtable.cpp +4 -6
  41. package/src/duckdb/src/function/function_binder.cpp +1 -1
  42. package/src/duckdb/src/function/table/arrow_conversion.cpp +2 -1
  43. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  44. package/src/duckdb/src/include/duckdb/common/arrow/appender/append_data.hpp +4 -0
  45. package/src/duckdb/src/include/duckdb/common/arrow/appender/enum_data.hpp +3 -1
  46. package/src/duckdb/src/include/duckdb/common/arrow/arrow_appender.hpp +2 -1
  47. package/src/duckdb/src/include/duckdb/common/arrow/arrow_wrapper.hpp +3 -0
  48. package/src/duckdb/src/include/duckdb/common/exception.hpp +1 -0
  49. package/src/duckdb/src/include/duckdb/common/preserved_error.hpp +1 -3
  50. package/src/duckdb/src/include/duckdb/execution/expression_executor_state.hpp +1 -1
  51. package/src/duckdb/src/include/duckdb/execution/operator/scan/csv/base_csv_reader.hpp +0 -4
  52. package/src/duckdb/src/include/duckdb/execution/operator/scan/csv/csv_sniffer.hpp +10 -10
  53. package/src/duckdb/src/include/duckdb/function/replacement_scan.hpp +20 -0
  54. package/src/duckdb/src/include/duckdb/main/config.hpp +2 -0
  55. package/src/duckdb/src/include/duckdb/optimizer/filter_pushdown.hpp +2 -0
  56. package/src/duckdb/src/include/duckdb/planner/binder.hpp +1 -0
  57. package/src/duckdb/src/include/duckdb/planner/bound_parameter_map.hpp +3 -0
  58. package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +2 -2
  59. package/src/duckdb/src/main/capi/arrow-c.cpp +7 -4
  60. package/src/duckdb/src/main/config.cpp +14 -0
  61. package/src/duckdb/src/main/extension/extension_install.cpp +14 -12
  62. package/src/duckdb/src/optimizer/filter_pushdown.cpp +1 -0
  63. package/src/duckdb/src/optimizer/pushdown/pushdown_distinct.cpp +19 -0
  64. package/src/duckdb/src/parser/transform/statement/transform_copy.cpp +4 -2
  65. package/src/duckdb/src/parser/transform/statement/transform_create_sequence.cpp +10 -5
  66. package/src/duckdb/src/planner/binder/expression/bind_between_expression.cpp +5 -7
  67. package/src/duckdb/src/planner/binder/expression/bind_collate_expression.cpp +4 -2
  68. package/src/duckdb/src/planner/binder/expression/bind_comparison_expression.cpp +17 -14
  69. package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +5 -12
  70. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +15 -1
  71. package/src/duckdb/src/planner/bound_parameter_map.cpp +16 -5
  72. package/src/duckdb/src/planner/expression_binder/base_select_binder.cpp +2 -5
  73. package/src/duckdb/src/planner/planner.cpp +1 -1
  74. package/src/duckdb/src/transaction/duck_transaction_manager.cpp +13 -9
  75. package/src/duckdb/third_party/parquet/parquet_types.h +2 -1
  76. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +5 -5
  77. package/src/duckdb/ub_src_optimizer_pushdown.cpp +2 -0
  78. package/src/statement.cpp +4 -4
  79. package/test/arrow.test.ts +3 -1
  80. package/test/parquet.test.ts +1 -1
  81. package/test/userdata1.parquet +0 -0
  82. package/{configure → vendor} +1 -1
  83. package/{configure.py → vendor.py} +12 -1
  84. package/duckdb_extension_config.cmake +0 -10
@@ -39,18 +39,18 @@ SnifferResult CSVSniffer::SniffCSV() {
39
39
  DetectDialect();
40
40
  // 2. Type Detection
41
41
  DetectTypes();
42
- // 3. Header Detection
42
+ // 3. Type Refinement
43
+ RefineTypes();
44
+ // 4. Header Detection
43
45
  DetectHeader();
44
46
  if (explicit_set_columns) {
45
47
  SetResultOptions();
46
48
  // We do not need to run type refinement, since the types have been given by the user
47
49
  return SnifferResult({}, {});
48
50
  }
49
- D_ASSERT(best_sql_types_candidates_per_column_idx.size() == names.size());
50
- // 4. Type Replacement
51
+ // 5. Type Replacement
51
52
  ReplaceTypes();
52
- // 5. Type Refinement
53
- RefineTypes();
53
+ D_ASSERT(best_sql_types_candidates_per_column_idx.size() == names.size());
54
54
  // We are done, Set the CSV Options in the reference. Construct and return the result.
55
55
  SetResultOptions();
56
56
  return SnifferResult(detected_types, names);
@@ -5,9 +5,9 @@ namespace duckdb {
5
5
 
6
6
  struct SniffDialect {
7
7
  inline static void Initialize(CSVStateMachine &machine) {
8
- machine.state = CSVState::STANDARD;
9
- machine.previous_state = CSVState::STANDARD;
10
- machine.pre_previous_state = CSVState::STANDARD;
8
+ machine.state = CSVState::EMPTY_LINE;
9
+ machine.previous_state = CSVState::EMPTY_LINE;
10
+ machine.pre_previous_state = CSVState::EMPTY_LINE;
11
11
  machine.cur_rows = 0;
12
12
  machine.column_count = 1;
13
13
  }
@@ -299,7 +299,7 @@ void CSVSniffer::DetectDialect() {
299
299
  unordered_map<uint8_t, vector<char>> quote_candidates_map;
300
300
  // Candidates for the escape option
301
301
  unordered_map<uint8_t, vector<char>> escape_candidates_map;
302
- escape_candidates_map[(uint8_t)QuoteRule::QUOTES_RFC] = {'\0', '\"', '\''};
302
+ escape_candidates_map[(uint8_t)QuoteRule::QUOTES_RFC] = {'\"', '\'', '\0'};
303
303
  escape_candidates_map[(uint8_t)QuoteRule::QUOTES_OTHER] = {'\\'};
304
304
  escape_candidates_map[(uint8_t)QuoteRule::NO_QUOTES] = {'\0'};
305
305
  // Number of rows read
@@ -14,7 +14,7 @@ void CSVSniffer::ReplaceTypes() {
14
14
  for (idx_t i = 0; i < names.size(); i++) {
15
15
  auto it = best_candidate->options.sql_types_per_column.find(names[i]);
16
16
  if (it != best_candidate->options.sql_types_per_column.end()) {
17
- best_sql_types_candidates_per_column_idx[i] = {best_candidate->options.sql_type_list[it->second]};
17
+ detected_types[i] = best_candidate->options.sql_type_list[it->second];
18
18
  found++;
19
19
  }
20
20
  }
@@ -33,7 +33,7 @@ void CSVSniffer::ReplaceTypes() {
33
33
  best_candidate->options.sql_type_list.size(), names.size());
34
34
  }
35
35
  for (idx_t i = 0; i < best_candidate->options.sql_type_list.size(); i++) {
36
- best_sql_types_candidates_per_column_idx[i] = {best_candidate->options.sql_type_list[i]};
36
+ detected_types[i] = best_candidate->options.sql_type_list[i];
37
37
  }
38
38
  }
39
39
  } // namespace duckdb
@@ -21,10 +21,7 @@ void PhysicalReset::ResetExtensionVariable(ExecutionContext &context, DBConfig &
21
21
 
22
22
  SourceResultType PhysicalReset::GetData(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const {
23
23
  auto &config = DBConfig::GetConfig(context.client);
24
- if (config.options.lock_configuration) {
25
- throw InvalidInputException("Cannot reset configuration option \"%s\" - the configuration has been locked",
26
- name);
27
- }
24
+ config.CheckLock(name);
28
25
  auto option = DBConfig::GetOptionByName(name);
29
26
  if (!option) {
30
27
  // check if this is an extra extension variable
@@ -24,10 +24,8 @@ void PhysicalSet::SetExtensionVariable(ClientContext &context, ExtensionOption &
24
24
 
25
25
  SourceResultType PhysicalSet::GetData(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const {
26
26
  auto &config = DBConfig::GetConfig(context.client);
27
- if (config.options.lock_configuration) {
28
- throw InvalidInputException("Cannot change configuration option \"%s\" - the configuration has been locked",
29
- name);
30
- }
27
+ // check if we are allowed to change the configuration option
28
+ config.CheckLock(name);
31
29
  auto option = DBConfig::GetOptionByName(name);
32
30
  if (!option) {
33
31
  // check if this is an extra extension variable
@@ -298,12 +298,10 @@ void PerfectAggregateHashTable::Destroy() {
298
298
  RowOperationsState row_state(*aggregate_allocator);
299
299
  data_ptr_t payload_ptr = data;
300
300
  for (idx_t i = 0; i < total_groups; i++) {
301
- if (group_is_set[i]) {
302
- data_pointers[count++] = payload_ptr;
303
- if (count == STANDARD_VECTOR_SIZE) {
304
- RowOperations::DestroyStates(row_state, layout, addresses, count);
305
- count = 0;
306
- }
301
+ data_pointers[count++] = payload_ptr;
302
+ if (count == STANDARD_VECTOR_SIZE) {
303
+ RowOperations::DestroyStates(row_state, layout, addresses, count);
304
+ count = 0;
307
305
  }
308
306
  payload_ptr += tuple_size;
309
307
  }
@@ -228,7 +228,7 @@ void FunctionBinder::CastToFunctionArguments(SimpleFunction &function, vector<un
228
228
  for (idx_t i = 0; i < children.size(); i++) {
229
229
  auto target_type = i < function.arguments.size() ? function.arguments[i] : function.varargs;
230
230
  target_type.Verify();
231
- // don't cast lambda children, they get removed anyways
231
+ // don't cast lambda children, they get removed before execution
232
232
  if (children[i]->return_type.id() == LogicalTypeId::LAMBDA) {
233
233
  continue;
234
234
  }
@@ -639,10 +639,11 @@ static void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowScanLoca
639
639
  for (idx_t type_idx = 0; type_idx < static_cast<idx_t>(array.n_children); type_idx++) {
640
640
  Vector child(members[type_idx].second);
641
641
  auto arrow_array = array.children[type_idx];
642
+ auto &child_type = arrow_type[type_idx];
642
643
 
643
644
  SetValidityMask(child, *arrow_array, scan_state, size, nested_offset);
644
645
 
645
- ColumnArrowToDuckDB(child, *arrow_array, scan_state, size, arrow_type, nested_offset, &validity_mask);
646
+ ColumnArrowToDuckDB(child, *arrow_array, scan_state, size, child_type, nested_offset, &validity_mask);
646
647
 
647
648
  children.push_back(std::move(child));
648
649
  }
@@ -1,8 +1,8 @@
1
1
  #ifndef DUCKDB_VERSION
2
- #define DUCKDB_VERSION "v0.9.1-dev95"
2
+ #define DUCKDB_VERSION "v0.9.1"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "e2b1788a25"
5
+ #define DUCKDB_SOURCE_ID "401c8061c6"
6
6
  #endif
7
7
  #include "duckdb/function/table/system_functions.hpp"
8
8
  #include "duckdb/main/database.hpp"
@@ -27,6 +27,7 @@ typedef void (*finalize_t)(ArrowAppendData &append_data, const LogicalType &type
27
27
  // ArrowAppendState
28
28
  struct ArrowAppendData {
29
29
  explicit ArrowAppendData(ClientProperties &options_p) : options(options_p) {
30
+ dictionary.release = nullptr;
30
31
  }
31
32
  // the buffers of the arrow vector
32
33
  ArrowBuffer validity;
@@ -48,6 +49,9 @@ struct ArrowAppendData {
48
49
  unique_ptr<ArrowArray> array;
49
50
  duckdb::array<const void *, 3> buffers = {{nullptr, nullptr, nullptr}};
50
51
  vector<ArrowArray *> child_pointers;
52
+ // Arrays so the children can be moved
53
+ vector<ArrowArray> child_arrays;
54
+ ArrowArray dictionary;
51
55
 
52
56
  ClientProperties options;
53
57
  };
@@ -62,7 +62,9 @@ struct ArrowEnumData : public ArrowScalarBaseData<TGT> {
62
62
  result->n_buffers = 2;
63
63
  result->buffers[1] = append_data.main_buffer.data();
64
64
  // finalize the enum child data, and assign it to the dictionary
65
- result->dictionary = ArrowAppender::FinalizeChild(LogicalType::VARCHAR, *append_data.child_data[0]);
65
+ result->dictionary = &append_data.dictionary;
66
+ append_data.dictionary =
67
+ *ArrowAppender::FinalizeChild(LogicalType::VARCHAR, std::move(append_data.child_data[0]));
66
68
  }
67
69
  };
68
70
 
@@ -28,9 +28,10 @@ public:
28
28
 
29
29
  public:
30
30
  static void ReleaseArray(ArrowArray *array);
31
- static ArrowArray *FinalizeChild(const LogicalType &type, ArrowAppendData &append_data);
31
+ static ArrowArray *FinalizeChild(const LogicalType &type, unique_ptr<ArrowAppendData> append_data);
32
32
  static unique_ptr<ArrowAppendData> InitializeChild(const LogicalType &type, idx_t capacity,
33
33
  ClientProperties &options);
34
+ static void AddChildren(ArrowAppendData &data, idx_t count);
34
35
 
35
36
  private:
36
37
  //! The types of the chunks that will be appended in
@@ -35,6 +35,9 @@ public:
35
35
  arrow_array.length = 0;
36
36
  arrow_array.release = nullptr;
37
37
  }
38
+ ArrowArrayWrapper(ArrowArrayWrapper &&other) : arrow_array(other.arrow_array) {
39
+ other.arrow_array.release = nullptr;
40
+ }
38
41
  ~ArrowArrayWrapper();
39
42
  };
40
43
 
@@ -97,6 +97,7 @@ public:
97
97
  DUCKDB_API const string &RawMessage() const;
98
98
 
99
99
  DUCKDB_API static string ExceptionTypeToString(ExceptionType type);
100
+ DUCKDB_API static ExceptionType StringToExceptionType(const string &type);
100
101
  [[noreturn]] DUCKDB_API static void ThrowAsTypeWithMessage(ExceptionType type, const string &message,
101
102
  const std::shared_ptr<Exception> &original);
102
103
  virtual std::shared_ptr<Exception> Copy() const {
@@ -18,9 +18,7 @@ public:
18
18
  //! Not initialized, default constructor
19
19
  DUCKDB_API PreservedError();
20
20
  //! From std::exception
21
- PreservedError(const std::exception &ex)
22
- : initialized(true), type(ExceptionType::INVALID), raw_message(SanitizeErrorMessage(ex.what())),
23
- exception_instance(nullptr) {
21
+ PreservedError(const std::exception &ex) : PreservedError(ex.what()) {
24
22
  }
25
23
  //! From a raw string
26
24
  DUCKDB_API explicit PreservedError(const string &raw_message);
@@ -33,7 +33,7 @@ struct ExpressionState {
33
33
 
34
34
  public:
35
35
  void AddChild(Expression *expr);
36
- void Finalize();
36
+ void Finalize(bool empty = false);
37
37
  Allocator &GetAllocator();
38
38
  bool HasContext();
39
39
  DUCKDB_API ClientContext &GetContext();
@@ -51,13 +51,9 @@ public:
51
51
  bool linenr_estimated = false;
52
52
 
53
53
  bool row_empty = false;
54
- idx_t sample_chunk_idx = 0;
55
- bool jumping_samples = false;
56
- bool end_of_file_reached = false;
57
54
  bool bom_checked = false;
58
55
 
59
56
  idx_t bytes_in_chunk = 0;
60
- double bytes_per_line_avg = 0;
61
57
 
62
58
  DataChunk parse_chunk;
63
59
 
@@ -34,9 +34,9 @@ public:
34
34
  //! CSV Sniffing consists of five steps:
35
35
  //! 1. Dialect Detection: Generate the CSV Options (delimiter, quote, escape, etc.)
36
36
  //! 2. Type Detection: Figures out the types of the columns (For one chunk)
37
- //! 3. Header Detection: Figures out if the CSV file has a header and produces the names of the columns
38
- //! 4. Type Replacement: Replaces the types of the columns if the user specified them
39
- //! 5. Type Refinement: Refines the types of the columns for the remaining chunks
37
+ //! 3. Type Refinement: Refines the types of the columns for the remaining chunks
38
+ //! 4. Header Detection: Figures out if the CSV file has a header and produces the names of the columns
39
+ //! 5. Type Replacement: Replaces the types of the columns if the user specified them
40
40
  SnifferResult SniffCSV();
41
41
 
42
42
  private:
@@ -107,6 +107,13 @@ private:
107
107
  idx_t best_start_without_header = 0;
108
108
  vector<Value> best_header_row;
109
109
 
110
+ //! ------------------------------------------------------//
111
+ //! ------------------ Type Refinement ------------------ //
112
+ //! ------------------------------------------------------//
113
+ void RefineTypes();
114
+ bool TryCastVector(Vector &parse_chunk_col, idx_t size, const LogicalType &sql_type);
115
+ vector<LogicalType> detected_types;
116
+
110
117
  //! ------------------------------------------------------//
111
118
  //! ------------------ Header Detection ----------------- //
112
119
  //! ------------------------------------------------------//
@@ -119,13 +126,6 @@ private:
119
126
  //! ------------------ Type Replacement ----------------- //
120
127
  //! ------------------------------------------------------//
121
128
  void ReplaceTypes();
122
-
123
- //! ------------------------------------------------------//
124
- //! ------------------ Type Refinement ------------------ //
125
- //! ------------------------------------------------------//
126
- void RefineTypes();
127
- bool TryCastVector(Vector &parse_chunk_col, idx_t size, const LogicalType &sql_type);
128
- vector<LogicalType> detected_types;
129
129
  };
130
130
 
131
131
  } // namespace duckdb
@@ -9,6 +9,7 @@
9
9
  #pragma once
10
10
 
11
11
  #include "duckdb/common/common.hpp"
12
+ #include "duckdb/common/string_util.hpp"
12
13
 
13
14
  namespace duckdb {
14
15
 
@@ -30,6 +31,25 @@ struct ReplacementScan {
30
31
  : function(function), data(std::move(data_p)) {
31
32
  }
32
33
 
34
+ static bool CanReplace(const string &table_name, const vector<string> &extensions) {
35
+ auto lower_name = StringUtil::Lower(table_name);
36
+
37
+ if (StringUtil::EndsWith(lower_name, ".gz")) {
38
+ lower_name = lower_name.substr(0, lower_name.size() - 3);
39
+ } else if (StringUtil::EndsWith(lower_name, ".zst")) {
40
+ lower_name = lower_name.substr(0, lower_name.size() - 4);
41
+ }
42
+
43
+ for (auto &extension : extensions) {
44
+ if (StringUtil::EndsWith(lower_name, "." + extension) ||
45
+ StringUtil::Contains(lower_name, "." + extension + "?")) {
46
+ return true;
47
+ }
48
+ }
49
+
50
+ return false;
51
+ }
52
+
33
53
  replacement_scan_t function;
34
54
  unique_ptr<ReplacementScanData> data;
35
55
  };
@@ -240,6 +240,8 @@ public:
240
240
  DUCKDB_API void SetOption(const string &name, Value value);
241
241
  DUCKDB_API void ResetOption(const string &name);
242
242
 
243
+ DUCKDB_API void CheckLock(const string &name);
244
+
243
245
  DUCKDB_API static idx_t ParseMemoryLimit(const string &arg);
244
246
 
245
247
  //! Return the list of possible compression functions for the specific physical type
@@ -43,6 +43,8 @@ private:
43
43
 
44
44
  //! Push down a LogicalAggregate op
45
45
  unique_ptr<LogicalOperator> PushdownAggregate(unique_ptr<LogicalOperator> op);
46
+ //! Push down a distinct operator
47
+ unique_ptr<LogicalOperator> PushdownDistinct(unique_ptr<LogicalOperator> op);
46
48
  //! Push down a LogicalFilter op
47
49
  unique_ptr<LogicalOperator> PushdownFilter(unique_ptr<LogicalOperator> op);
48
50
  //! Push down a LogicalCrossProduct op
@@ -362,6 +362,7 @@ private:
362
362
 
363
363
  //! If only a schema name is provided (e.g. "a.b") then figure out if "a" is a schema or a catalog name
364
364
  void BindSchemaOrCatalog(string &catalog_name, string &schema_name);
365
+ const string BindCatalog(string &catalog_name);
365
366
  SchemaCatalogEntry &BindCreateSchema(CreateInfo &info);
366
367
 
367
368
  unique_ptr<BoundQueryNode> BindSelectNode(SelectNode &statement, unique_ptr<BoundTableRef> from_table);
@@ -35,6 +35,9 @@ public:
35
35
 
36
36
  unique_ptr<BoundParameterExpression> BindParameterExpression(ParameterExpression &expr);
37
37
 
38
+ //! Flag to indicate that we need to rebind this prepared statement before execution
39
+ bool rebind = false;
40
+
38
41
  private:
39
42
  shared_ptr<BoundParameterData> CreateOrGetData(const string &identifier);
40
43
  void CreateNewParameter(const string &id, const shared_ptr<BoundParameterData> &param_data);
@@ -90,8 +90,8 @@ public:
90
90
  void QualifyColumnNames(unique_ptr<ParsedExpression> &expr);
91
91
  static void QualifyColumnNames(Binder &binder, unique_ptr<ParsedExpression> &expr);
92
92
 
93
- static unique_ptr<Expression> PushCollation(ClientContext &context, unique_ptr<Expression> source,
94
- const string &collation, bool equality_only = false);
93
+ static bool PushCollation(ClientContext &context, unique_ptr<Expression> &source, const LogicalType &sql_type,
94
+ bool equality_only = false);
95
95
  static void TestCollation(ClientContext &context, const string &collation);
96
96
 
97
97
  bool BindCorrelatedColumns(unique_ptr<ParsedExpression> &expr);
@@ -64,7 +64,7 @@ duckdb_state duckdb_prepared_arrow_schema(duckdb_prepared_statement prepared, du
64
64
  if (result_schema->release) {
65
65
  // Need to release the existing schema before we overwrite it
66
66
  result_schema->release(result_schema);
67
- result_schema->release = nullptr;
67
+ D_ASSERT(!result_schema->release);
68
68
  }
69
69
 
70
70
  ArrowConverter::ToArrowSchema(result_schema, prepared_types, prepared_names, properties);
@@ -155,14 +155,17 @@ struct PrivateData {
155
155
 
156
156
  // LCOV_EXCL_START
157
157
  // This function is never called, but used to set ArrowSchema's release functions to a non-null NOOP.
158
- void EmptySchemaRelease(ArrowSchema *) {
158
+ void EmptySchemaRelease(ArrowSchema *schema) {
159
+ schema->release = nullptr;
159
160
  }
160
161
  // LCOV_EXCL_STOP
161
162
 
162
- void EmptyArrayRelease(ArrowArray *) {
163
+ void EmptyArrayRelease(ArrowArray *array) {
164
+ array->release = nullptr;
163
165
  }
164
166
 
165
- void EmptyStreamRelease(ArrowArrayStream *) {
167
+ void EmptyStreamRelease(ArrowArrayStream *stream) {
168
+ stream->release = nullptr;
166
169
  }
167
170
 
168
171
  void FactoryGetSchema(uintptr_t stream_factory_ptr, duckdb::ArrowSchemaWrapper &schema) {
@@ -233,6 +233,20 @@ void DBConfig::SetDefaultMaxMemory() {
233
233
  }
234
234
  }
235
235
 
236
+ void DBConfig::CheckLock(const string &name) {
237
+ if (!options.lock_configuration) {
238
+ // not locked
239
+ return;
240
+ }
241
+ case_insensitive_set_t allowed_settings {"schema", "search_path"};
242
+ if (allowed_settings.find(name) != allowed_settings.end()) {
243
+ // we are always allowed to change these settings
244
+ return;
245
+ }
246
+ // not allowed!
247
+ throw InvalidInputException("Cannot change configuration option \"%s\" - the configuration has been locked", name);
248
+ }
249
+
236
250
  idx_t CGroupBandwidthQuota(idx_t physical_cores, FileSystem &fs) {
237
251
  static constexpr const char *CPU_MAX = "/sys/fs/cgroup/cpu.max";
238
252
  static constexpr const char *CFS_QUOTA = "/sys/fs/cgroup/cpu/cpu.cfs_quota_us";
@@ -208,18 +208,20 @@ void ExtensionHelper::InstallExtensionInternal(DBConfig &config, ClientConfig *c
208
208
  fs.RemoveFile(temp_path);
209
209
  }
210
210
  auto is_http_url = StringUtil::Contains(extension, "http://");
211
- if (fs.FileExists(extension)) {
212
- idx_t file_size;
213
- auto in_buffer = ReadExtensionFileFromDisk(fs, extension, file_size);
214
- WriteExtensionFileToDisk(fs, temp_path, in_buffer.get(), file_size);
215
-
216
- if (fs.FileExists(local_extension_path) && force_install) {
217
- fs.RemoveFile(local_extension_path);
211
+ if (ExtensionHelper::IsFullPath(extension)) {
212
+ if (fs.FileExists(extension)) {
213
+ idx_t file_size;
214
+ auto in_buffer = ReadExtensionFileFromDisk(fs, extension, file_size);
215
+ WriteExtensionFileToDisk(fs, temp_path, in_buffer.get(), file_size);
216
+
217
+ if (fs.FileExists(local_extension_path) && force_install) {
218
+ fs.RemoveFile(local_extension_path);
219
+ }
220
+ fs.MoveFile(temp_path, local_extension_path);
221
+ return;
222
+ } else if (!is_http_url) {
223
+ throw IOException("Failed to read extension from \"%s\": no such file", extension);
218
224
  }
219
- fs.MoveFile(temp_path, local_extension_path);
220
- return;
221
- } else if (StringUtil::Contains(extension, "/") && !is_http_url) {
222
- throw IOException("Failed to read extension from \"%s\": no such file", extension);
223
225
  }
224
226
 
225
227
  #ifdef DISABLE_DUCKDB_REMOTE_INSTALL
@@ -280,7 +282,7 @@ void ExtensionHelper::InstallExtensionInternal(DBConfig &config, ClientConfig *c
280
282
  // create suggestions
281
283
  string message;
282
284
  auto exact_match = ExtensionHelper::CreateSuggestions(extension_name, message);
283
- if (exact_match) {
285
+ if (exact_match && !IsRelease(DuckDB::LibraryVersion())) {
284
286
  message += "\nAre you using a development build? In this case, extensions might not (yet) be uploaded.";
285
287
  }
286
288
  if (res.error() == duckdb_httplib::Error::Success) {
@@ -33,6 +33,7 @@ unique_ptr<LogicalOperator> FilterPushdown::Rewrite(unique_ptr<LogicalOperator>
33
33
  case LogicalOperatorType::LOGICAL_UNION:
34
34
  return PushdownSetOperation(std::move(op));
35
35
  case LogicalOperatorType::LOGICAL_DISTINCT:
36
+ return PushdownDistinct(std::move(op));
36
37
  case LogicalOperatorType::LOGICAL_ORDER_BY: {
37
38
  // we can just push directly through these operations without any rewriting
38
39
  op->children[0] = Rewrite(std::move(op->children[0]));
@@ -0,0 +1,19 @@
1
+ #include "duckdb/optimizer/filter_pushdown.hpp"
2
+ #include "duckdb/planner/expression_iterator.hpp"
3
+ #include "duckdb/planner/operator/logical_distinct.hpp"
4
+
5
+ namespace duckdb {
6
+
7
+ unique_ptr<LogicalOperator> FilterPushdown::PushdownDistinct(unique_ptr<LogicalOperator> op) {
8
+ D_ASSERT(op->type == LogicalOperatorType::LOGICAL_DISTINCT);
9
+ auto &distinct = op->Cast<LogicalDistinct>();
10
+ if (!distinct.order_by) {
11
+ // regular DISTINCT - can just push down
12
+ op->children[0] = Rewrite(std::move(op->children[0]));
13
+ return op;
14
+ }
15
+ // no pushdown through DISTINCT ON (yet?)
16
+ return FinishPushdown(std::move(op));
17
+ }
18
+
19
+ } // namespace duckdb
@@ -1,6 +1,7 @@
1
1
  #include "duckdb/common/string_util.hpp"
2
2
  #include "duckdb/common/types/value.hpp"
3
3
  #include "duckdb/core_functions/scalar/struct_functions.hpp"
4
+ #include "duckdb/function/replacement_scan.hpp"
4
5
  #include "duckdb/parser/expression/constant_expression.hpp"
5
6
  #include "duckdb/parser/expression/function_expression.hpp"
6
7
  #include "duckdb/parser/statement/copy_statement.hpp"
@@ -82,9 +83,10 @@ unique_ptr<CopyStatement> Transformer::TransformCopy(duckdb_libpgquery::PGCopySt
82
83
  // copy to a file
83
84
  info.file_path = stmt.filename;
84
85
  }
85
- if (StringUtil::EndsWith(info.file_path, ".parquet")) {
86
+
87
+ if (ReplacementScan::CanReplace(info.file_path, {"parquet"})) {
86
88
  info.format = "parquet";
87
- } else if (StringUtil::EndsWith(info.file_path, ".json") || StringUtil::EndsWith(info.file_path, ".ndjson")) {
89
+ } else if (ReplacementScan::CanReplace(info.file_path, {"json", "jsonl", "ndjson"})) {
88
90
  info.format = "json";
89
91
  } else {
90
92
  info.format = "csv";
@@ -17,6 +17,8 @@ unique_ptr<CreateStatement> Transformer::TransformCreateSequence(duckdb_libpgque
17
17
  info->name = qname.name;
18
18
 
19
19
  if (stmt.options) {
20
+ int64_t default_start_value = info->start_value;
21
+ bool has_start_value = false;
20
22
  unordered_set<SequenceInfo, EnumClassHash> used;
21
23
  duckdb_libpgquery::PGListCell *cell = nullptr;
22
24
  for_each_cell(cell, stmt.options->head) {
@@ -51,10 +53,10 @@ unique_ptr<CreateStatement> Transformer::TransformCreateSequence(duckdb_libpgque
51
53
  throw ParserException("Increment must not be zero");
52
54
  }
53
55
  if (info->increment < 0) {
54
- info->start_value = info->max_value = -1;
56
+ default_start_value = info->max_value = -1;
55
57
  info->min_value = NumericLimits<int64_t>::Minimum();
56
58
  } else {
57
- info->start_value = info->min_value = 1;
59
+ default_start_value = info->min_value = 1;
58
60
  info->max_value = NumericLimits<int64_t>::Maximum();
59
61
  }
60
62
  } else if (opt_name == "minvalue") {
@@ -68,7 +70,7 @@ unique_ptr<CreateStatement> Transformer::TransformCreateSequence(duckdb_libpgque
68
70
 
69
71
  info->min_value = opt_value;
70
72
  if (info->increment > 0) {
71
- info->start_value = info->min_value;
73
+ default_start_value = info->min_value;
72
74
  }
73
75
  } else if (opt_name == "maxvalue") {
74
76
  if (used.find(SequenceInfo::SEQ_MAX) != used.end()) {
@@ -81,7 +83,7 @@ unique_ptr<CreateStatement> Transformer::TransformCreateSequence(duckdb_libpgque
81
83
 
82
84
  info->max_value = opt_value;
83
85
  if (info->increment < 0) {
84
- info->start_value = info->max_value;
86
+ default_start_value = info->max_value;
85
87
  }
86
88
  } else if (opt_name == "start") {
87
89
  if (used.find(SequenceInfo::SEQ_START) != used.end()) {
@@ -91,7 +93,7 @@ unique_ptr<CreateStatement> Transformer::TransformCreateSequence(duckdb_libpgque
91
93
  if (nodef) {
92
94
  continue;
93
95
  }
94
-
96
+ has_start_value = true;
95
97
  info->start_value = opt_value;
96
98
  } else if (opt_name == "cycle") {
97
99
  if (used.find(SequenceInfo::SEQ_CYCLE) != used.end()) {
@@ -107,6 +109,9 @@ unique_ptr<CreateStatement> Transformer::TransformCreateSequence(duckdb_libpgque
107
109
  throw ParserException("Unrecognized option \"%s\" for CREATE SEQUENCE", opt_name);
108
110
  }
109
111
  }
112
+ if (!has_start_value) {
113
+ info->start_value = default_start_value;
114
+ }
110
115
  }
111
116
  info->temporary = !stmt.sequence->relpersistence;
112
117
  info->on_conflict = TransformOnConflict(stmt.onconflict);
@@ -34,13 +34,11 @@ BindResult ExpressionBinder::BindExpression(BetweenExpression &expr, idx_t depth
34
34
  input = BoundCastExpression::AddCastToType(context, std::move(input), input_type);
35
35
  lower = BoundCastExpression::AddCastToType(context, std::move(lower), input_type);
36
36
  upper = BoundCastExpression::AddCastToType(context, std::move(upper), input_type);
37
- if (input_type.id() == LogicalTypeId::VARCHAR) {
38
- // handle collation
39
- auto collation = StringType::GetCollation(input_type);
40
- input = PushCollation(context, std::move(input), collation, false);
41
- lower = PushCollation(context, std::move(lower), collation, false);
42
- upper = PushCollation(context, std::move(upper), collation, false);
43
- }
37
+ // handle collation
38
+ PushCollation(context, input, input_type, false);
39
+ PushCollation(context, lower, input_type, false);
40
+ PushCollation(context, upper, input_type, false);
41
+
44
42
  if (!input->HasSideEffects() && !input->HasParameter() && !input->HasSubquery()) {
45
43
  // the expression does not have side effects and can be copied: create two comparisons
46
44
  // the reason we do this is that individual comparisons are easier to handle in optimizers
@@ -18,8 +18,10 @@ BindResult ExpressionBinder::BindExpression(CollateExpression &expr, idx_t depth
18
18
  throw BinderException("collations are only supported for type varchar");
19
19
  }
20
20
  // Validate the collation, but don't use it
21
- PushCollation(context, child->Copy(), expr.collation, false);
22
- child->return_type = LogicalType::VARCHAR_COLLATION(expr.collation);
21
+ auto child_copy = child->Copy();
22
+ auto collation_type = LogicalType::VARCHAR_COLLATION(expr.collation);
23
+ PushCollation(context, child_copy, collation_type, false);
24
+ child->return_type = collation_type;
23
25
  return BindResult(std::move(child));
24
26
  }
25
27