duckdb 1.1.4-dev9.0 → 1.2.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 (220) hide show
  1. package/LICENSE +1 -1
  2. package/binding.gyp +1 -0
  3. package/package.json +2 -2
  4. package/src/duckdb/extension/core_functions/function_list.cpp +1 -0
  5. package/src/duckdb/extension/core_functions/include/core_functions/scalar/map_functions.hpp +9 -0
  6. package/src/duckdb/extension/core_functions/scalar/date/current.cpp +1 -0
  7. package/src/duckdb/extension/core_functions/scalar/generic/can_implicitly_cast.cpp +2 -2
  8. package/src/duckdb/extension/core_functions/scalar/generic/typeof.cpp +1 -1
  9. package/src/duckdb/extension/core_functions/scalar/list/flatten.cpp +91 -61
  10. package/src/duckdb/extension/core_functions/scalar/map/map_extract.cpp +89 -8
  11. package/src/duckdb/extension/icu/icu-current.cpp +63 -0
  12. package/src/duckdb/extension/icu/icu-makedate.cpp +43 -39
  13. package/src/duckdb/extension/icu/icu-timezone.cpp +63 -63
  14. package/src/duckdb/extension/icu/icu_extension.cpp +2 -0
  15. package/src/duckdb/extension/icu/include/icu-casts.hpp +39 -0
  16. package/src/duckdb/extension/icu/include/icu-current.hpp +17 -0
  17. package/src/duckdb/extension/icu/third_party/icu/stubdata/stubdata.cpp +1 -1
  18. package/src/duckdb/extension/json/json_functions/json_structure.cpp +3 -1
  19. package/src/duckdb/extension/parquet/column_writer.cpp +26 -18
  20. package/src/duckdb/extension/parquet/include/parquet_reader.hpp +0 -6
  21. package/src/duckdb/extension/parquet/include/parquet_writer.hpp +15 -1
  22. package/src/duckdb/extension/parquet/include/resizable_buffer.hpp +1 -0
  23. package/src/duckdb/extension/parquet/parquet_extension.cpp +67 -15
  24. package/src/duckdb/extension/parquet/parquet_reader.cpp +5 -3
  25. package/src/duckdb/extension/parquet/parquet_writer.cpp +5 -6
  26. package/src/duckdb/src/catalog/catalog.cpp +21 -8
  27. package/src/duckdb/src/catalog/catalog_search_path.cpp +17 -1
  28. package/src/duckdb/src/catalog/catalog_set.cpp +1 -1
  29. package/src/duckdb/src/catalog/default/default_functions.cpp +0 -3
  30. package/src/duckdb/src/catalog/dependency_list.cpp +7 -0
  31. package/src/duckdb/src/common/adbc/adbc.cpp +1 -56
  32. package/src/duckdb/src/common/arrow/arrow_converter.cpp +3 -2
  33. package/src/duckdb/src/common/arrow/arrow_type_extension.cpp +58 -28
  34. package/src/duckdb/src/common/arrow/schema_metadata.cpp +1 -1
  35. package/src/duckdb/src/common/compressed_file_system.cpp +6 -2
  36. package/src/duckdb/src/common/enum_util.cpp +26 -22
  37. package/src/duckdb/src/common/error_data.cpp +3 -2
  38. package/src/duckdb/src/common/gzip_file_system.cpp +8 -8
  39. package/src/duckdb/src/common/local_file_system.cpp +2 -2
  40. package/src/duckdb/src/common/multi_file_reader.cpp +1 -1
  41. package/src/duckdb/src/common/random_engine.cpp +4 -1
  42. package/src/duckdb/src/common/serializer/memory_stream.cpp +23 -19
  43. package/src/duckdb/src/common/serializer/serializer.cpp +1 -1
  44. package/src/duckdb/src/common/types/bit.cpp +1 -1
  45. package/src/duckdb/src/common/types/column/column_data_allocator.cpp +0 -5
  46. package/src/duckdb/src/common/types/column/column_data_collection.cpp +4 -1
  47. package/src/duckdb/src/common/types/data_chunk.cpp +2 -1
  48. package/src/duckdb/src/common/types/row/tuple_data_segment.cpp +0 -4
  49. package/src/duckdb/src/common/types.cpp +1 -1
  50. package/src/duckdb/src/execution/index/art/art.cpp +52 -42
  51. package/src/duckdb/src/execution/index/art/leaf.cpp +4 -9
  52. package/src/duckdb/src/execution/index/art/node.cpp +13 -13
  53. package/src/duckdb/src/execution/index/art/prefix.cpp +21 -16
  54. package/src/duckdb/src/execution/index/bound_index.cpp +6 -8
  55. package/src/duckdb/src/execution/index/fixed_size_allocator.cpp +39 -34
  56. package/src/duckdb/src/execution/index/fixed_size_buffer.cpp +2 -1
  57. package/src/duckdb/src/execution/index/unbound_index.cpp +10 -0
  58. package/src/duckdb/src/execution/operator/aggregate/physical_streaming_window.cpp +62 -44
  59. package/src/duckdb/src/execution/operator/csv_scanner/scanner/column_count_scanner.cpp +26 -0
  60. package/src/duckdb/src/execution/operator/csv_scanner/scanner/string_value_scanner.cpp +69 -40
  61. package/src/duckdb/src/execution/operator/csv_scanner/sniffer/dialect_detection.cpp +3 -7
  62. package/src/duckdb/src/execution/operator/csv_scanner/sniffer/header_detection.cpp +11 -5
  63. package/src/duckdb/src/execution/operator/csv_scanner/sniffer/type_detection.cpp +4 -0
  64. package/src/duckdb/src/execution/operator/csv_scanner/state_machine/csv_state_machine_cache.cpp +8 -8
  65. package/src/duckdb/src/execution/operator/csv_scanner/util/csv_error.cpp +36 -12
  66. package/src/duckdb/src/execution/operator/csv_scanner/util/csv_reader_options.cpp +12 -9
  67. package/src/duckdb/src/execution/operator/join/physical_hash_join.cpp +0 -1
  68. package/src/duckdb/src/execution/operator/persistent/physical_copy_database.cpp +29 -1
  69. package/src/duckdb/src/execution/operator/persistent/physical_delete.cpp +58 -10
  70. package/src/duckdb/src/execution/operator/persistent/physical_insert.cpp +58 -35
  71. package/src/duckdb/src/execution/operator/schema/physical_create_art_index.cpp +2 -1
  72. package/src/duckdb/src/execution/radix_partitioned_hashtable.cpp +9 -4
  73. package/src/duckdb/src/execution/sample/reservoir_sample.cpp +7 -6
  74. package/src/duckdb/src/function/compression_config.cpp +4 -0
  75. package/src/duckdb/src/function/function_binder.cpp +1 -1
  76. package/src/duckdb/src/function/scalar/system/write_log.cpp +2 -2
  77. package/src/duckdb/src/function/table/arrow/arrow_duck_schema.cpp +15 -2
  78. package/src/duckdb/src/function/table/arrow_conversion.cpp +10 -10
  79. package/src/duckdb/src/function/table/copy_csv.cpp +8 -5
  80. package/src/duckdb/src/function/table/read_csv.cpp +21 -4
  81. package/src/duckdb/src/function/table/sniff_csv.cpp +7 -0
  82. package/src/duckdb/src/function/table/system/duckdb_extensions.cpp +4 -0
  83. package/src/duckdb/src/function/table/system/duckdb_secret_types.cpp +71 -0
  84. package/src/duckdb/src/function/table/system_functions.cpp +1 -0
  85. package/src/duckdb/src/function/table/table_scan.cpp +120 -36
  86. package/src/duckdb/src/function/table/version/pragma_version.cpp +4 -4
  87. package/src/duckdb/src/function/window/window_aggregate_function.cpp +6 -1
  88. package/src/duckdb/src/function/window/window_boundaries_state.cpp +135 -11
  89. package/src/duckdb/src/function/window/window_segment_tree.cpp +50 -22
  90. package/src/duckdb/src/function/window/window_token_tree.cpp +4 -3
  91. package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +4 -0
  92. package/src/duckdb/src/include/duckdb/catalog/catalog_search_path.hpp +2 -0
  93. package/src/duckdb/src/include/duckdb/catalog/dependency_list.hpp +1 -0
  94. package/src/duckdb/src/include/duckdb/common/arrow/arrow_type_extension.hpp +4 -2
  95. package/src/duckdb/src/include/duckdb/common/enum_util.hpp +8 -8
  96. package/src/duckdb/src/include/duckdb/common/multi_file_reader.hpp +0 -2
  97. package/src/duckdb/src/include/duckdb/common/serializer/deserializer.hpp +8 -3
  98. package/src/duckdb/src/include/duckdb/common/serializer/memory_stream.hpp +6 -1
  99. package/src/duckdb/src/include/duckdb/common/serializer/serialization_data.hpp +25 -0
  100. package/src/duckdb/src/include/duckdb/common/serializer/serializer.hpp +9 -3
  101. package/src/duckdb/src/include/duckdb/common/types/selection_vector.hpp +1 -1
  102. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +11 -14
  103. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +5 -4
  104. package/src/duckdb/src/include/duckdb/execution/index/bound_index.hpp +21 -10
  105. package/src/duckdb/src/include/duckdb/execution/index/fixed_size_allocator.hpp +6 -5
  106. package/src/duckdb/src/include/duckdb/execution/index/fixed_size_buffer.hpp +37 -32
  107. package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/base_scanner.hpp +36 -1
  108. package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/column_count_scanner.hpp +3 -0
  109. package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/sniffer/csv_sniffer.hpp +2 -0
  110. package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/state_machine_options.hpp +5 -5
  111. package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/string_value_scanner.hpp +5 -30
  112. package/src/duckdb/src/include/duckdb/execution/reservoir_sample.hpp +7 -1
  113. package/src/duckdb/src/include/duckdb/function/scalar_function.hpp +3 -3
  114. package/src/duckdb/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp +1 -0
  115. package/src/duckdb/src/include/duckdb/function/table/system_functions.hpp +4 -0
  116. package/src/duckdb/src/include/duckdb/function/window/window_boundaries_state.hpp +2 -2
  117. package/src/duckdb/src/include/duckdb/logging/logger.hpp +40 -119
  118. package/src/duckdb/src/include/duckdb/logging/logging.hpp +0 -2
  119. package/src/duckdb/src/include/duckdb/main/config.hpp +5 -0
  120. package/src/duckdb/src/include/duckdb/main/connection.hpp +0 -8
  121. package/src/duckdb/src/include/duckdb/main/connection_manager.hpp +2 -1
  122. package/src/duckdb/src/include/duckdb/main/extension.hpp +1 -0
  123. package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +11 -7
  124. package/src/duckdb/src/include/duckdb/main/extension_helper.hpp +1 -0
  125. package/src/duckdb/src/include/duckdb/main/secret/secret.hpp +2 -0
  126. package/src/duckdb/src/include/duckdb/main/secret/secret_manager.hpp +3 -0
  127. package/src/duckdb/src/include/duckdb/main/settings.hpp +10 -0
  128. package/src/duckdb/src/include/duckdb/parser/constraint.hpp +9 -0
  129. package/src/duckdb/src/include/duckdb/parser/expression/window_expression.hpp +36 -9
  130. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_view_info.hpp +2 -1
  131. package/src/duckdb/src/include/duckdb/parser/query_node/set_operation_node.hpp +8 -2
  132. package/src/duckdb/src/include/duckdb/planner/binder.hpp +4 -0
  133. package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_data.hpp +9 -1
  134. package/src/duckdb/src/include/duckdb/planner/filter/constant_filter.hpp +1 -0
  135. package/src/duckdb/src/include/duckdb/planner/filter/in_filter.hpp +0 -2
  136. package/src/duckdb/src/include/duckdb/planner/filter/optional_filter.hpp +4 -4
  137. package/src/duckdb/src/include/duckdb/planner/table_filter.hpp +1 -1
  138. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +14 -10
  139. package/src/duckdb/src/include/duckdb/storage/index_storage_info.hpp +4 -0
  140. package/src/duckdb/src/include/duckdb/storage/single_file_block_manager.hpp +6 -1
  141. package/src/duckdb/src/include/duckdb/storage/storage_info.hpp +7 -2
  142. package/src/duckdb/src/include/duckdb/storage/storage_manager.hpp +9 -0
  143. package/src/duckdb/src/include/duckdb/storage/storage_options.hpp +2 -0
  144. package/src/duckdb/src/include/duckdb/storage/string_uncompressed.hpp +4 -3
  145. package/src/duckdb/src/include/duckdb/storage/table/column_data.hpp +2 -0
  146. package/src/duckdb/src/include/duckdb/storage/table/table_index_list.hpp +6 -4
  147. package/src/duckdb/src/include/duckdb/storage/table/table_statistics.hpp +1 -1
  148. package/src/duckdb/src/include/duckdb/storage/write_ahead_log.hpp +2 -0
  149. package/src/duckdb/src/include/duckdb/transaction/local_storage.hpp +2 -0
  150. package/src/duckdb/src/include/duckdb/transaction/meta_transaction.hpp +1 -1
  151. package/src/duckdb/src/logging/logger.cpp +8 -66
  152. package/src/duckdb/src/main/attached_database.cpp +3 -1
  153. package/src/duckdb/src/main/client_context.cpp +4 -2
  154. package/src/duckdb/src/main/config.cpp +20 -2
  155. package/src/duckdb/src/main/connection.cpp +2 -29
  156. package/src/duckdb/src/main/connection_manager.cpp +5 -3
  157. package/src/duckdb/src/main/database.cpp +2 -2
  158. package/src/duckdb/src/main/extension/extension_helper.cpp +4 -5
  159. package/src/duckdb/src/main/extension/extension_install.cpp +23 -10
  160. package/src/duckdb/src/main/extension/extension_load.cpp +6 -7
  161. package/src/duckdb/src/main/extension.cpp +27 -9
  162. package/src/duckdb/src/main/secret/secret_manager.cpp +11 -0
  163. package/src/duckdb/src/main/settings/custom_settings.cpp +44 -0
  164. package/src/duckdb/src/optimizer/column_lifetime_analyzer.cpp +6 -0
  165. package/src/duckdb/src/optimizer/filter_combiner.cpp +13 -3
  166. package/src/duckdb/src/optimizer/filter_pushdown.cpp +33 -6
  167. package/src/duckdb/src/optimizer/late_materialization.cpp +14 -3
  168. package/src/duckdb/src/optimizer/remove_unused_columns.cpp +0 -3
  169. package/src/duckdb/src/parser/parsed_data/attach_info.cpp +5 -1
  170. package/src/duckdb/src/parser/parsed_data/create_view_info.cpp +6 -3
  171. package/src/duckdb/src/parser/query_node/set_operation_node.cpp +49 -0
  172. package/src/duckdb/src/parser/transform/expression/transform_columnref.cpp +1 -0
  173. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +50 -12
  174. package/src/duckdb/src/planner/binder/expression/bind_columnref_expression.cpp +7 -5
  175. package/src/duckdb/src/planner/binder/expression/bind_comparison_expression.cpp +1 -0
  176. package/src/duckdb/src/planner/binder/expression/bind_operator_expression.cpp +2 -2
  177. package/src/duckdb/src/planner/binder/expression/bind_star_expression.cpp +12 -2
  178. package/src/duckdb/src/planner/binder/statement/bind_copy_database.cpp +0 -1
  179. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +55 -39
  180. package/src/duckdb/src/planner/binder/statement/bind_execute.cpp +2 -1
  181. package/src/duckdb/src/planner/binder/tableref/bind_basetableref.cpp +15 -7
  182. package/src/duckdb/src/planner/binder/tableref/bind_showref.cpp +13 -8
  183. package/src/duckdb/src/planner/binder/tableref/bind_table_function.cpp +8 -3
  184. package/src/duckdb/src/planner/expression/bound_function_expression.cpp +17 -1
  185. package/src/duckdb/src/planner/expression_binder/index_binder.cpp +1 -0
  186. package/src/duckdb/src/planner/filter/conjunction_filter.cpp +1 -0
  187. package/src/duckdb/src/planner/filter/constant_filter.cpp +21 -0
  188. package/src/duckdb/src/planner/filter/in_filter.cpp +4 -7
  189. package/src/duckdb/src/planner/logical_operator.cpp +5 -3
  190. package/src/duckdb/src/planner/planner.cpp +1 -1
  191. package/src/duckdb/src/planner/subquery/flatten_dependent_join.cpp +2 -0
  192. package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +3 -4
  193. package/src/duckdb/src/storage/checkpoint_manager.cpp +3 -5
  194. package/src/duckdb/src/storage/compression/dictionary/decompression.cpp +4 -4
  195. package/src/duckdb/src/storage/compression/fsst.cpp +2 -2
  196. package/src/duckdb/src/storage/compression/roaring/common.cpp +10 -1
  197. package/src/duckdb/src/storage/compression/string_uncompressed.cpp +11 -6
  198. package/src/duckdb/src/storage/compression/validity_uncompressed.cpp +4 -0
  199. package/src/duckdb/src/storage/compression/zstd.cpp +6 -0
  200. package/src/duckdb/src/storage/data_table.cpp +104 -109
  201. package/src/duckdb/src/storage/local_storage.cpp +8 -6
  202. package/src/duckdb/src/storage/magic_bytes.cpp +1 -1
  203. package/src/duckdb/src/storage/serialization/serialize_dependency.cpp +3 -3
  204. package/src/duckdb/src/storage/serialization/serialize_nodes.cpp +3 -3
  205. package/src/duckdb/src/storage/serialization/serialize_query_node.cpp +7 -5
  206. package/src/duckdb/src/storage/single_file_block_manager.cpp +95 -28
  207. package/src/duckdb/src/storage/storage_info.cpp +38 -0
  208. package/src/duckdb/src/storage/storage_manager.cpp +11 -0
  209. package/src/duckdb/src/storage/table/column_data.cpp +4 -0
  210. package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +3 -3
  211. package/src/duckdb/src/storage/table/row_group_collection.cpp +67 -68
  212. package/src/duckdb/src/storage/table/table_statistics.cpp +4 -4
  213. package/src/duckdb/src/storage/table_index_list.cpp +41 -15
  214. package/src/duckdb/src/storage/wal_replay.cpp +3 -1
  215. package/src/duckdb/src/storage/write_ahead_log.cpp +11 -4
  216. package/src/duckdb/src/transaction/meta_transaction.cpp +1 -1
  217. package/src/duckdb/src/verification/deserialized_statement_verifier.cpp +2 -1
  218. package/src/duckdb/third_party/httplib/httplib.hpp +0 -1
  219. package/src/duckdb/third_party/re2/util/logging.h +10 -10
  220. package/src/duckdb/ub_src_function_table_system.cpp +2 -0
@@ -149,11 +149,15 @@ unique_ptr<GlobalTableFunctionState> DuckDBExtensionsInit(ClientContext &context
149
149
  auto entry = installed_extensions.find(ext_name);
150
150
  if (entry == installed_extensions.end() || !entry->second.installed) {
151
151
  ExtensionInformation &info = installed_extensions[ext_name];
152
+
152
153
  info.name = ext_name;
153
154
  info.loaded = true;
154
155
  info.extension_version = ext_install_info->version;
155
156
  info.installed = ext_install_info->mode == ExtensionInstallMode::STATICALLY_LINKED;
156
157
  info.install_mode = ext_install_info->mode;
158
+ if (ext_data.install_info->mode == ExtensionInstallMode::STATICALLY_LINKED && info.file_path.empty()) {
159
+ info.file_path = "(BUILT-IN)";
160
+ }
157
161
  } else {
158
162
  entry->second.loaded = true;
159
163
  entry->second.extension_version = ext_install_info->version;
@@ -0,0 +1,71 @@
1
+ #include "duckdb/function/table/system_functions.hpp"
2
+ #include "duckdb/main/config.hpp"
3
+ #include "duckdb/main/client_context.hpp"
4
+ #include "duckdb/common/enum_util.hpp"
5
+ #include "duckdb/main/secret/secret_manager.hpp"
6
+ #include "duckdb/main/secret/secret.hpp"
7
+
8
+ namespace duckdb {
9
+
10
+ struct DuckDBSecretTypesData : public GlobalTableFunctionState {
11
+ DuckDBSecretTypesData() : offset(0) {
12
+ }
13
+
14
+ vector<SecretType> types;
15
+ idx_t offset;
16
+ };
17
+
18
+ static unique_ptr<FunctionData> DuckDBSecretTypesBind(ClientContext &context, TableFunctionBindInput &input,
19
+ vector<LogicalType> &return_types, vector<string> &names) {
20
+ names.emplace_back("type");
21
+ return_types.emplace_back(LogicalType::VARCHAR);
22
+
23
+ names.emplace_back("default_provider");
24
+ return_types.emplace_back(LogicalType::VARCHAR);
25
+
26
+ names.emplace_back("extension");
27
+ return_types.emplace_back(LogicalType::VARCHAR);
28
+
29
+ return nullptr;
30
+ }
31
+
32
+ unique_ptr<GlobalTableFunctionState> DuckDBSecretTypesInit(ClientContext &context, TableFunctionInitInput &input) {
33
+ auto result = make_uniq<DuckDBSecretTypesData>();
34
+
35
+ auto &secret_manager = SecretManager::Get(context);
36
+ result->types = secret_manager.AllSecretTypes();
37
+
38
+ return std::move(result);
39
+ }
40
+
41
+ void DuckDBSecretTypesFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) {
42
+ auto &data = data_p.global_state->Cast<DuckDBSecretTypesData>();
43
+ if (data.offset >= data.types.size()) {
44
+ // finished returning values
45
+ return;
46
+ }
47
+ // start returning values
48
+ // either fill up the chunk or return all the remaining columns
49
+ idx_t count = 0;
50
+ while (data.offset < data.types.size() && count < STANDARD_VECTOR_SIZE) {
51
+ auto &entry = data.types[data.offset++];
52
+
53
+ // return values:
54
+ // type, LogicalType::VARCHAR
55
+ output.SetValue(0, count, Value(entry.name));
56
+ // default_provider, LogicalType::VARCHAR
57
+ output.SetValue(1, count, Value(entry.default_provider));
58
+ // extension, LogicalType::VARCHAR
59
+ output.SetValue(2, count, Value(entry.extension));
60
+
61
+ count++;
62
+ }
63
+ output.SetCardinality(count);
64
+ }
65
+
66
+ void DuckDBSecretTypesFun::RegisterFunction(BuiltinFunctions &set) {
67
+ set.AddFunction(TableFunction("duckdb_secret_types", {}, DuckDBSecretTypesFunction, DuckDBSecretTypesBind,
68
+ DuckDBSecretTypesInit));
69
+ }
70
+
71
+ } // namespace duckdb
@@ -33,6 +33,7 @@ void BuiltinFunctions::RegisterSQLiteFunctions() {
33
33
  DuckDBOptimizersFun::RegisterFunction(*this);
34
34
  DuckDBSecretsFun::RegisterFunction(*this);
35
35
  DuckDBWhichSecretFun::RegisterFunction(*this);
36
+ DuckDBSecretTypesFun::RegisterFunction(*this);
36
37
  DuckDBSequencesFun::RegisterFunction(*this);
37
38
  DuckDBSettingsFun::RegisterFunction(*this);
38
39
  DuckDBTablesFun::RegisterFunction(*this);
@@ -24,6 +24,7 @@
24
24
  #include "duckdb/planner/expression/bound_constant_expression.hpp"
25
25
  #include "duckdb/planner/expression/bound_comparison_expression.hpp"
26
26
  #include "duckdb/planner/filter/conjunction_filter.hpp"
27
+ #include "duckdb/common/types/value_map.hpp"
27
28
 
28
29
  namespace duckdb {
29
30
 
@@ -41,6 +42,8 @@ struct IndexScanLocalState : public LocalTableFunctionState {
41
42
  //! The DataChunk containing all read columns.
42
43
  //! This includes filter columns, which are immediately removed.
43
44
  DataChunk all_columns;
45
+ //! Fetch state
46
+ ColumnFetchState fetch_state;
44
47
  };
45
48
 
46
49
  static StorageIndex TransformStorageIndex(const ColumnIndex &column_id) {
@@ -115,7 +118,6 @@ public:
115
118
  //! Synchronize changes to the global index scan state.
116
119
  mutex index_scan_lock;
117
120
 
118
- ColumnFetchState fetch_state;
119
121
  TableScanState table_scan_state;
120
122
 
121
123
  public:
@@ -159,10 +161,10 @@ public:
159
161
 
160
162
  if (CanRemoveFilterColumns()) {
161
163
  l_state.all_columns.Reset();
162
- storage.Fetch(tx, l_state.all_columns, column_ids, local_vector, scan_count, fetch_state);
164
+ storage.Fetch(tx, l_state.all_columns, column_ids, local_vector, scan_count, l_state.fetch_state);
163
165
  output.ReferenceColumns(l_state.all_columns, projection_ids);
164
166
  } else {
165
- storage.Fetch(tx, output, column_ids, local_vector, scan_count, fetch_state);
167
+ storage.Fetch(tx, output, column_ids, local_vector, scan_count, l_state.fetch_state);
166
168
  }
167
169
  }
168
170
 
@@ -361,56 +363,137 @@ unique_ptr<GlobalTableFunctionState> DuckIndexScanInitGlobal(ClientContext &cont
361
363
  return std::move(g_state);
362
364
  }
363
365
 
364
- void ExtractInFilter(unique_ptr<TableFilter> &filter, BoundColumnRefExpression &bound_ref,
365
- unique_ptr<vector<unique_ptr<Expression>>> &filter_expressions) {
366
- // Special-handling of IN filters.
367
- // They are part of a CONJUNCTION_AND.
368
- if (filter->filter_type != TableFilterType::CONJUNCTION_AND) {
369
- return;
366
+ void ExtractExpressionsFromValues(value_set_t &unique_values, BoundColumnRefExpression &bound_ref,
367
+ vector<unique_ptr<Expression>> &expressions) {
368
+ for (const auto &value : unique_values) {
369
+ auto bound_constant = make_uniq<BoundConstantExpression>(value);
370
+ auto filter_expr = make_uniq<BoundComparisonExpression>(ExpressionType::COMPARE_EQUAL, bound_ref.Copy(),
371
+ std::move(bound_constant));
372
+ expressions.push_back(std::move(filter_expr));
370
373
  }
374
+ }
371
375
 
372
- auto &and_filter = filter->Cast<ConjunctionAndFilter>();
373
- auto &children = and_filter.child_filters;
374
- if (children.empty()) {
375
- return;
376
+ void ExtractIn(InFilter &filter, BoundColumnRefExpression &bound_ref, vector<unique_ptr<Expression>> &expressions) {
377
+ // Eliminate any duplicates.
378
+ value_set_t unique_values;
379
+ for (const auto &value : filter.values) {
380
+ if (unique_values.find(value) == unique_values.end()) {
381
+ unique_values.insert(value);
382
+ }
376
383
  }
377
- if (children[0]->filter_type != TableFilterType::OPTIONAL_FILTER) {
384
+ ExtractExpressionsFromValues(unique_values, bound_ref, expressions);
385
+ }
386
+
387
+ void ExtractConjunctionAnd(ConjunctionAndFilter &filter, BoundColumnRefExpression &bound_ref,
388
+ vector<unique_ptr<Expression>> &expressions) {
389
+ if (filter.child_filters.empty()) {
378
390
  return;
379
391
  }
380
392
 
381
- auto &optional_filter = children[0]->Cast<OptionalFilter>();
382
- auto &child = optional_filter.child_filter;
383
- if (child->filter_type != TableFilterType::IN_FILTER) {
393
+ // Extract the CONSTANT_COMPARISON and IN_FILTER children.
394
+ vector<reference<ConstantFilter>> comparisons;
395
+ vector<reference<InFilter>> in_filters;
396
+
397
+ for (idx_t i = 0; i < filter.child_filters.size(); i++) {
398
+ if (filter.child_filters[i]->filter_type == TableFilterType::CONSTANT_COMPARISON) {
399
+ auto &comparison = filter.child_filters[i]->Cast<ConstantFilter>();
400
+ comparisons.push_back(comparison);
401
+ continue;
402
+ }
403
+
404
+ if (filter.child_filters[i]->filter_type == TableFilterType::OPTIONAL_FILTER) {
405
+ auto &optional_filter = filter.child_filters[i]->Cast<OptionalFilter>();
406
+ if (!optional_filter.child_filter) {
407
+ return;
408
+ }
409
+ if (optional_filter.child_filter->filter_type != TableFilterType::IN_FILTER) {
410
+ // No support for other optional filter types yet.
411
+ return;
412
+ }
413
+ auto &in_filter = optional_filter.child_filter->Cast<InFilter>();
414
+ in_filters.push_back(in_filter);
415
+ continue;
416
+ }
417
+
418
+ // No support for other filter types than CONSTANT_COMPARISON and IN_FILTER in CONJUNCTION_AND yet.
384
419
  return;
385
420
  }
386
421
 
387
- auto &in_filter = child->Cast<InFilter>();
388
- if (!in_filter.origin_is_hash_join) {
422
+ // No support for other CONJUNCTION_AND cases yet.
423
+ if (in_filters.empty()) {
389
424
  return;
390
425
  }
391
426
 
392
- // They are all on the same column, so we can split them.
393
- for (const auto &value : in_filter.values) {
394
- auto bound_constant = make_uniq<BoundConstantExpression>(value);
395
- auto filter_expr = make_uniq<BoundComparisonExpression>(ExpressionType::COMPARE_EQUAL, bound_ref.Copy(),
396
- std::move(bound_constant));
397
- filter_expressions->push_back(std::move(filter_expr));
427
+ // Get the combined unique values of the IN filters.
428
+ value_set_t unique_values;
429
+ for (idx_t filter_idx = 0; filter_idx < in_filters.size(); filter_idx++) {
430
+ auto &in_filter = in_filters[filter_idx].get();
431
+ for (idx_t value_idx = 0; value_idx < in_filter.values.size(); value_idx++) {
432
+ auto &value = in_filter.values[value_idx];
433
+ if (unique_values.find(value) != unique_values.end()) {
434
+ continue;
435
+ }
436
+ unique_values.insert(value);
437
+ }
438
+ }
439
+
440
+ // Extract all qualifying values.
441
+ for (auto value_it = unique_values.begin(); value_it != unique_values.end();) {
442
+ bool qualifies = true;
443
+ for (idx_t comp_idx = 0; comp_idx < comparisons.size(); comp_idx++) {
444
+ if (!comparisons[comp_idx].get().Compare(*value_it)) {
445
+ qualifies = false;
446
+ value_it = unique_values.erase(value_it);
447
+ break;
448
+ }
449
+ }
450
+ if (qualifies) {
451
+ value_it++;
452
+ }
453
+ }
454
+
455
+ ExtractExpressionsFromValues(unique_values, bound_ref, expressions);
456
+ }
457
+
458
+ void ExtractFilter(TableFilter &filter, BoundColumnRefExpression &bound_ref,
459
+ vector<unique_ptr<Expression>> &expressions) {
460
+ switch (filter.filter_type) {
461
+ case TableFilterType::OPTIONAL_FILTER: {
462
+ auto &optional_filter = filter.Cast<OptionalFilter>();
463
+ if (!optional_filter.child_filter) {
464
+ return;
465
+ }
466
+ return ExtractFilter(*optional_filter.child_filter, bound_ref, expressions);
467
+ }
468
+ case TableFilterType::IN_FILTER: {
469
+ auto &in_filter = filter.Cast<InFilter>();
470
+ ExtractIn(in_filter, bound_ref, expressions);
471
+ return;
472
+ }
473
+ case TableFilterType::CONJUNCTION_AND: {
474
+ auto &conjunction_and = filter.Cast<ConjunctionAndFilter>();
475
+ ExtractConjunctionAnd(conjunction_and, bound_ref, expressions);
476
+ return;
477
+ }
478
+ default:
479
+ return;
398
480
  }
399
481
  }
400
482
 
401
- unique_ptr<vector<unique_ptr<Expression>>> ExtractFilters(const ColumnDefinition &col, unique_ptr<TableFilter> &filter,
402
- idx_t storage_idx) {
483
+ vector<unique_ptr<Expression>> ExtractFilterExpressions(const ColumnDefinition &col, unique_ptr<TableFilter> &filter,
484
+ idx_t storage_idx) {
403
485
  ColumnBinding binding(0, storage_idx);
404
486
  auto bound_ref = make_uniq<BoundColumnRefExpression>(col.Name(), col.Type(), binding);
405
487
 
406
- auto filter_expressions = make_uniq<vector<unique_ptr<Expression>>>();
407
- ExtractInFilter(filter, *bound_ref, filter_expressions);
488
+ vector<unique_ptr<Expression>> expressions;
489
+ ExtractFilter(*filter, *bound_ref, expressions);
408
490
 
409
- if (filter_expressions->empty()) {
491
+ // Attempt matching the top-level filter to the index expression.
492
+ if (expressions.empty()) {
410
493
  auto filter_expr = filter->ToExpression(*bound_ref);
411
- filter_expressions->push_back(std::move(filter_expr));
494
+ expressions.push_back(std::move(filter_expr));
412
495
  }
413
- return filter_expressions;
496
+ return expressions;
414
497
  }
415
498
 
416
499
  bool TryScanIndex(ART &art, const ColumnList &column_list, TableFunctionInitInput &input, TableFilterSet &filter_set,
@@ -453,8 +536,8 @@ bool TryScanIndex(ART &art, const ColumnList &column_list, TableFunctionInitInpu
453
536
  return false;
454
537
  }
455
538
 
456
- auto filter_expressions = ExtractFilters(col, filter->second, storage_index.GetIndex());
457
- for (const auto &filter_expr : *filter_expressions) {
539
+ auto expressions = ExtractFilterExpressions(col, filter->second, storage_index.GetIndex());
540
+ for (const auto &filter_expr : expressions) {
458
541
  auto scan_state = art.TryInitializeScan(*index_expr, *filter_expr);
459
542
  if (!scan_state) {
460
543
  return false;
@@ -493,7 +576,8 @@ unique_ptr<GlobalTableFunctionState> TableScanInitGlobal(ClientContext &context,
493
576
  }
494
577
 
495
578
  // The checkpoint lock ensures that we do not checkpoint while scanning this table.
496
- auto checkpoint_lock = storage.GetSharedCheckpointLock();
579
+ auto &transaction = DuckTransaction::Get(context, storage.db);
580
+ auto checkpoint_lock = transaction.SharedLockTable(*storage.GetDataTableInfo());
497
581
  auto &info = storage.GetDataTableInfo();
498
582
  auto &indexes = info->GetIndexes();
499
583
  if (indexes.Empty()) {
@@ -588,7 +672,7 @@ InsertionOrderPreservingMap<string> TableScanToString(TableFunctionToStringInput
588
672
  InsertionOrderPreservingMap<string> result;
589
673
  auto &bind_data = input.bind_data->Cast<TableScanBindData>();
590
674
  result["Table"] = bind_data.table.name;
591
- result["Type"] = bind_data.is_index_scan ? "Index Scan" : "Sequence Scan";
675
+ result["Type"] = bind_data.is_index_scan ? "Index Scan" : "Sequential Scan";
592
676
  return result;
593
677
  }
594
678
 
@@ -1,17 +1,17 @@
1
1
  #ifndef DUCKDB_PATCH_VERSION
2
- #define DUCKDB_PATCH_VERSION "4-dev4615"
2
+ #define DUCKDB_PATCH_VERSION "0"
3
3
  #endif
4
4
  #ifndef DUCKDB_MINOR_VERSION
5
- #define DUCKDB_MINOR_VERSION 1
5
+ #define DUCKDB_MINOR_VERSION 2
6
6
  #endif
7
7
  #ifndef DUCKDB_MAJOR_VERSION
8
8
  #define DUCKDB_MAJOR_VERSION 1
9
9
  #endif
10
10
  #ifndef DUCKDB_VERSION
11
- #define DUCKDB_VERSION "v1.1.4-dev4615"
11
+ #define DUCKDB_VERSION "v1.2.0"
12
12
  #endif
13
13
  #ifndef DUCKDB_SOURCE_ID
14
- #define DUCKDB_SOURCE_ID "ff6dde1453"
14
+ #define DUCKDB_SOURCE_ID "5f5512b827"
15
15
  #endif
16
16
  #include "duckdb/function/table/system_functions.hpp"
17
17
  #include "duckdb/main/database.hpp"
@@ -194,7 +194,12 @@ static void ApplyWindowStats(const WindowBoundary &boundary, FrameDelta &delta,
194
194
  case WindowBoundary::EXPR_PRECEDING_RANGE:
195
195
  case WindowBoundary::EXPR_FOLLOWING_RANGE:
196
196
  return;
197
- default:
197
+ case WindowBoundary::CURRENT_ROW_GROUPS:
198
+ case WindowBoundary::EXPR_PRECEDING_GROUPS:
199
+ case WindowBoundary::EXPR_FOLLOWING_GROUPS:
200
+ return;
201
+ case WindowBoundary::INVALID:
202
+ throw InternalException(is_start ? "Unknown window start boundary" : "Unknown window end boundary");
198
203
  break;
199
204
  }
200
205
 
@@ -374,7 +374,7 @@ WindowBoundsSet WindowBoundariesState::GetWindowBounds(const BoundWindowExpressi
374
374
  result.insert(FRAME_END);
375
375
  break;
376
376
  default:
377
- throw InternalException("Window aggregate type %s", ExpressionTypeToString(wexpr.GetExpressionType()));
377
+ throw InternalException("Window expression type %s", ExpressionTypeToString(wexpr.GetExpressionType()));
378
378
  }
379
379
 
380
380
  // Internal dependencies
@@ -388,11 +388,12 @@ WindowBoundsSet WindowBoundariesState::GetWindowBounds(const BoundWindowExpressi
388
388
  result.insert(PEER_END);
389
389
  }
390
390
 
391
- // If the frames are RANGE, then we need peer boundaries
392
- // If they are preceding or following, we also need to know
391
+ // If the frames are RANGE or GROUPS, then we need peer boundaries
392
+ // If they are preceding or following, RANGE also needs to know
393
393
  // where the valid values begin or end.
394
394
  switch (wexpr.start) {
395
395
  case WindowBoundary::CURRENT_ROW_RANGE:
396
+ case WindowBoundary::CURRENT_ROW_GROUPS:
396
397
  result.insert(PEER_BEGIN);
397
398
  break;
398
399
  case WindowBoundary::EXPR_PRECEDING_RANGE:
@@ -404,12 +405,24 @@ WindowBoundsSet WindowBoundariesState::GetWindowBounds(const BoundWindowExpressi
404
405
  result.insert(PEER_BEGIN);
405
406
  result.insert(VALID_END);
406
407
  break;
407
- default:
408
+ case WindowBoundary::EXPR_PRECEDING_GROUPS:
409
+ result.insert(PEER_BEGIN);
410
+ break;
411
+ case WindowBoundary::EXPR_FOLLOWING_GROUPS:
412
+ result.insert(PEER_BEGIN);
413
+ break;
414
+ case WindowBoundary::UNBOUNDED_PRECEDING:
415
+ case WindowBoundary::UNBOUNDED_FOLLOWING:
416
+ case WindowBoundary::CURRENT_ROW_ROWS:
417
+ case WindowBoundary::EXPR_PRECEDING_ROWS:
418
+ case WindowBoundary::EXPR_FOLLOWING_ROWS:
419
+ case WindowBoundary::INVALID:
408
420
  break;
409
421
  }
410
422
 
411
423
  switch (wexpr.end) {
412
424
  case WindowBoundary::CURRENT_ROW_RANGE:
425
+ case WindowBoundary::CURRENT_ROW_GROUPS:
413
426
  result.insert(PEER_END);
414
427
  break;
415
428
  case WindowBoundary::EXPR_PRECEDING_RANGE:
@@ -421,7 +434,18 @@ WindowBoundsSet WindowBoundariesState::GetWindowBounds(const BoundWindowExpressi
421
434
  result.insert(VALID_BEGIN);
422
435
  result.insert(VALID_END);
423
436
  break;
424
- default:
437
+ case WindowBoundary::EXPR_PRECEDING_GROUPS:
438
+ result.insert(PEER_END);
439
+ break;
440
+ case WindowBoundary::EXPR_FOLLOWING_GROUPS:
441
+ result.insert(PEER_END);
442
+ break;
443
+ case WindowBoundary::UNBOUNDED_PRECEDING:
444
+ case WindowBoundary::UNBOUNDED_FOLLOWING:
445
+ case WindowBoundary::CURRENT_ROW_ROWS:
446
+ case WindowBoundary::EXPR_PRECEDING_ROWS:
447
+ case WindowBoundary::EXPR_FOLLOWING_ROWS:
448
+ case WindowBoundary::INVALID:
425
449
  break;
426
450
  }
427
451
  }
@@ -483,10 +507,10 @@ void WindowBoundariesState::Bounds(DataChunk &bounds, idx_t row_idx, optional_pt
483
507
  ValidEnd(bounds, row_idx, count, is_jump, partition_mask, order_mask, range);
484
508
  }
485
509
  if (required.count(FRAME_BEGIN)) {
486
- FrameBegin(bounds, row_idx, count, boundary_start, range);
510
+ FrameBegin(bounds, row_idx, count, boundary_start, order_mask, range);
487
511
  }
488
512
  if (required.count(FRAME_END)) {
489
- FrameEnd(bounds, row_idx, count, boundary_end, range);
513
+ FrameEnd(bounds, row_idx, count, boundary_end, order_mask, range);
490
514
  }
491
515
  next_pos += count;
492
516
 
@@ -683,7 +707,8 @@ void WindowBoundariesState::ValidEnd(DataChunk &bounds, idx_t row_idx, const idx
683
707
  }
684
708
 
685
709
  void WindowBoundariesState::FrameBegin(DataChunk &bounds, idx_t row_idx, const idx_t count,
686
- WindowInputExpression &boundary_begin, optional_ptr<WindowCursor> range) {
710
+ WindowInputExpression &boundary_begin, const ValidityMask &order_mask,
711
+ optional_ptr<WindowCursor> range) {
687
712
  auto partition_begin_data = FlatVector::GetData<idx_t>(bounds.data[PARTITION_BEGIN]);
688
713
  auto partition_end_data = FlatVector::GetData<const idx_t>(bounds.data[PARTITION_END]);
689
714
  auto peer_begin_data = FlatVector::GetData<idx_t>(bounds.data[PEER_BEGIN]);
@@ -704,6 +729,9 @@ void WindowBoundariesState::FrameBegin(DataChunk &bounds, idx_t row_idx, const i
704
729
  }
705
730
  break;
706
731
  case WindowBoundary::CURRENT_ROW_RANGE:
732
+ case WindowBoundary::CURRENT_ROW_GROUPS:
733
+ // in RANGE or GROUPS mode it means that the frame starts or ends with the current row's
734
+ // first or last peer in the ORDER BY ordering
707
735
  bounds.data[FRAME_BEGIN].Reference(bounds.data[PEER_BEGIN]);
708
736
  frame_begin_data = peer_begin_data;
709
737
  break;
@@ -759,7 +787,53 @@ void WindowBoundariesState::FrameBegin(DataChunk &bounds, idx_t row_idx, const i
759
787
  frame_begin_data[chunk_idx] = window_start;
760
788
  }
761
789
  break;
762
- default:
790
+ case WindowBoundary::EXPR_PRECEDING_GROUPS:
791
+ // In GROUPS mode, the offset is an integer indicating that the frame starts or ends that many peer groups
792
+ // before or after the current row's peer group, where a peer group is a group of rows that are equivalent
793
+ // according to the window's ORDER BY clause.
794
+ for (idx_t chunk_idx = 0; chunk_idx < count; ++chunk_idx, ++row_idx) {
795
+ if (boundary_begin.CellIsNull(chunk_idx)) {
796
+ window_start = peer_begin_data[chunk_idx];
797
+ } else {
798
+ // Count peer groups backwards.
799
+ const auto peer_begin = peer_begin_data[chunk_idx];
800
+ const auto partition_begin = partition_begin_data[chunk_idx];
801
+ const auto boundary = boundary_begin.GetCell<int64_t>(chunk_idx);
802
+ if (boundary < 0) {
803
+ throw OutOfRangeException("Invalid GROUPS PRECEDING value");
804
+ } else if (!boundary) {
805
+ window_start = peer_begin;
806
+ } else {
807
+ auto n = UnsafeNumericCast<idx_t>(boundary);
808
+ window_start = FindPrevStart(order_mask, partition_begin, peer_begin, n);
809
+ }
810
+ }
811
+ frame_begin_data[chunk_idx] = window_start;
812
+ }
813
+ break;
814
+ case WindowBoundary::EXPR_FOLLOWING_GROUPS:
815
+ for (idx_t chunk_idx = 0; chunk_idx < count; ++chunk_idx, ++row_idx) {
816
+ if (boundary_begin.CellIsNull(chunk_idx)) {
817
+ window_start = peer_begin_data[chunk_idx];
818
+ } else {
819
+ // Count peer groups forward.
820
+ const auto peer_begin = peer_begin_data[chunk_idx];
821
+ const auto partition_end = partition_end_data[chunk_idx];
822
+ const auto boundary = boundary_begin.GetCell<int64_t>(chunk_idx);
823
+ if (boundary < 0) {
824
+ throw OutOfRangeException("Invalid GROUPS FOLLOWING value");
825
+ } else if (!boundary) {
826
+ window_start = peer_begin;
827
+ } else {
828
+ auto n = UnsafeNumericCast<idx_t>(boundary);
829
+ window_start = FindNextStart(order_mask, peer_begin + 1, partition_end, n);
830
+ }
831
+ }
832
+ frame_begin_data[chunk_idx] = window_start;
833
+ }
834
+ break;
835
+ case WindowBoundary::UNBOUNDED_FOLLOWING:
836
+ case WindowBoundary::INVALID:
763
837
  throw InternalException("Unsupported window start boundary");
764
838
  }
765
839
 
@@ -767,7 +841,8 @@ void WindowBoundariesState::FrameBegin(DataChunk &bounds, idx_t row_idx, const i
767
841
  }
768
842
 
769
843
  void WindowBoundariesState::FrameEnd(DataChunk &bounds, idx_t row_idx, const idx_t count,
770
- WindowInputExpression &boundary_end, optional_ptr<WindowCursor> range) {
844
+ WindowInputExpression &boundary_end, const ValidityMask &order_mask,
845
+ optional_ptr<WindowCursor> range) {
771
846
  auto partition_begin_data = FlatVector::GetData<const idx_t>(bounds.data[PARTITION_BEGIN]);
772
847
  auto partition_end_data = FlatVector::GetData<idx_t>(bounds.data[PARTITION_END]);
773
848
  auto peer_end_data = FlatVector::GetData<idx_t>(bounds.data[PEER_END]);
@@ -784,6 +859,9 @@ void WindowBoundariesState::FrameEnd(DataChunk &bounds, idx_t row_idx, const idx
784
859
  }
785
860
  break;
786
861
  case WindowBoundary::CURRENT_ROW_RANGE:
862
+ case WindowBoundary::CURRENT_ROW_GROUPS:
863
+ // in RANGE or GROUPS mode it means that the frame starts or ends with the current row's
864
+ // first or last peer in the ORDER BY ordering
787
865
  bounds.data[FRAME_END].Reference(bounds.data[PEER_END]);
788
866
  frame_end_data = peer_end_data;
789
867
  break;
@@ -844,7 +922,53 @@ void WindowBoundariesState::FrameEnd(DataChunk &bounds, idx_t row_idx, const idx
844
922
  frame_end_data[chunk_idx] = window_end;
845
923
  }
846
924
  break;
847
- default:
925
+ case WindowBoundary::EXPR_PRECEDING_GROUPS:
926
+ // In GROUPS mode, the offset is an integer indicating that the frame starts or ends that many peer groups
927
+ // before or after the current row's peer group, where a peer group is a group of rows that are equivalent
928
+ // according to the window's ORDER BY clause.
929
+ for (idx_t chunk_idx = 0; chunk_idx < count; ++chunk_idx, ++row_idx) {
930
+ if (boundary_end.CellIsNull(chunk_idx)) {
931
+ window_end = peer_end_data[chunk_idx];
932
+ } else {
933
+ // Count peer groups backwards.
934
+ const auto peer_end = peer_end_data[chunk_idx];
935
+ const auto partition_begin = partition_begin_data[chunk_idx];
936
+ const auto boundary = boundary_end.GetCell<int64_t>(chunk_idx);
937
+ if (boundary < 0) {
938
+ throw OutOfRangeException("Invalid GROUPS PRECEDING value");
939
+ } else if (!boundary) {
940
+ window_end = peer_end;
941
+ } else {
942
+ auto n = UnsafeNumericCast<idx_t>(boundary);
943
+ window_end = FindPrevStart(order_mask, partition_begin, peer_end, n);
944
+ }
945
+ }
946
+ frame_end_data[chunk_idx] = window_end;
947
+ }
948
+ break;
949
+ case WindowBoundary::EXPR_FOLLOWING_GROUPS:
950
+ for (idx_t chunk_idx = 0; chunk_idx < count; ++chunk_idx, ++row_idx) {
951
+ if (boundary_end.CellIsNull(chunk_idx)) {
952
+ window_end = peer_end_data[chunk_idx];
953
+ } else {
954
+ // Count peer groups forward.
955
+ const auto peer_end = peer_end_data[chunk_idx];
956
+ const auto partition_end = partition_end_data[chunk_idx];
957
+ const auto boundary = boundary_end.GetCell<int64_t>(chunk_idx);
958
+ if (boundary < 0) {
959
+ throw OutOfRangeException("Invalid GROUPS FOLLOWING value");
960
+ } else if (!boundary) {
961
+ window_end = peer_end;
962
+ } else {
963
+ auto n = UnsafeNumericCast<idx_t>(boundary);
964
+ window_end = FindNextStart(order_mask, peer_end + 1, partition_end, n);
965
+ }
966
+ }
967
+ frame_end_data[chunk_idx] = window_end;
968
+ }
969
+ break;
970
+ case WindowBoundary::UNBOUNDED_PRECEDING:
971
+ case WindowBoundary::INVALID:
848
972
  throw InternalException("Unsupported window end boundary");
849
973
  }
850
974