duckdb 0.8.2-dev3250.0 → 0.8.2-dev3300.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 (45) hide show
  1. package/package.json +1 -1
  2. package/src/duckdb/extension/parquet/column_reader.cpp +18 -4
  3. package/src/duckdb/extension/parquet/include/parquet_timestamp.hpp +1 -0
  4. package/src/duckdb/extension/parquet/include/parquet_writer.hpp +4 -0
  5. package/src/duckdb/extension/parquet/parquet_extension.cpp +3 -0
  6. package/src/duckdb/extension/parquet/parquet_statistics.cpp +18 -2
  7. package/src/duckdb/extension/parquet/parquet_timestamp.cpp +6 -0
  8. package/src/duckdb/extension/parquet/parquet_writer.cpp +69 -15
  9. package/src/duckdb/src/common/enum_util.cpp +5 -0
  10. package/src/duckdb/src/common/operator/cast_operators.cpp +57 -0
  11. package/src/duckdb/src/common/operator/string_cast.cpp +45 -8
  12. package/src/duckdb/src/common/types/time.cpp +105 -0
  13. package/src/duckdb/src/common/types/value.cpp +7 -8
  14. package/src/duckdb/src/common/types/vector.cpp +1 -1
  15. package/src/duckdb/src/execution/column_binding_resolver.cpp +7 -0
  16. package/src/duckdb/src/execution/operator/schema/{physical_create_index.cpp → physical_create_art_index.cpp} +37 -46
  17. package/src/duckdb/src/execution/physical_plan/plan_create_index.cpp +12 -4
  18. package/src/duckdb/src/function/cast/string_cast.cpp +2 -1
  19. package/src/duckdb/src/function/cast/time_casts.cpp +7 -6
  20. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  21. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/index_catalog_entry.hpp +1 -0
  22. package/src/duckdb/src/include/duckdb/common/enums/index_type.hpp +3 -2
  23. package/src/duckdb/src/include/duckdb/common/operator/cast_operators.hpp +22 -1
  24. package/src/duckdb/src/include/duckdb/common/operator/string_cast.hpp +1 -1
  25. package/src/duckdb/src/include/duckdb/common/types/datetime.hpp +46 -3
  26. package/src/duckdb/src/include/duckdb/common/types/time.hpp +5 -0
  27. package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -1
  28. package/src/duckdb/src/include/duckdb/execution/operator/schema/{physical_create_index.hpp → physical_create_art_index.hpp} +5 -5
  29. package/src/duckdb/src/include/duckdb/function/copy_function.hpp +6 -1
  30. package/src/duckdb/src/include/duckdb/function/udf_function.hpp +2 -1
  31. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_index_info.hpp +5 -0
  32. package/src/duckdb/src/include/duckdb/planner/operator/logical_extension_operator.hpp +3 -0
  33. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +1 -1
  34. package/src/duckdb/src/main/appender.cpp +3 -1
  35. package/src/duckdb/src/main/capi/result-c.cpp +3 -1
  36. package/src/duckdb/src/parser/parsed_data/create_index_info.cpp +14 -0
  37. package/src/duckdb/src/parser/transform/statement/transform_create_index.cpp +27 -13
  38. package/src/duckdb/src/planner/binder/statement/bind_export.cpp +29 -4
  39. package/src/duckdb/src/planner/operator/logical_extension_operator.cpp +15 -0
  40. package/src/duckdb/src/storage/index.cpp +3 -25
  41. package/src/duckdb/src/storage/local_storage.cpp +0 -1
  42. package/src/duckdb/src/storage/serialization/serialize_create_info.cpp +4 -0
  43. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  44. package/src/duckdb/ub_src_execution_operator_schema.cpp +1 -1
  45. package/test/test_all_types.test.ts +1 -1
@@ -1,4 +1,4 @@
1
- #include "duckdb/execution/operator/schema/physical_create_index.hpp"
1
+ #include "duckdb/execution/operator/schema/physical_create_art_index.hpp"
2
2
 
3
3
  #include "duckdb/catalog/catalog_entry/duck_table_entry.hpp"
4
4
  #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
@@ -14,10 +14,10 @@
14
14
 
15
15
  namespace duckdb {
16
16
 
17
- PhysicalCreateIndex::PhysicalCreateIndex(LogicalOperator &op, TableCatalogEntry &table_p,
18
- const vector<column_t> &column_ids, unique_ptr<CreateIndexInfo> info,
19
- vector<unique_ptr<Expression>> unbound_expressions,
20
- idx_t estimated_cardinality, const bool sorted)
17
+ PhysicalCreateARTIndex::PhysicalCreateARTIndex(LogicalOperator &op, TableCatalogEntry &table_p,
18
+ const vector<column_t> &column_ids, unique_ptr<CreateIndexInfo> info,
19
+ vector<unique_ptr<Expression>> unbound_expressions,
20
+ idx_t estimated_cardinality, const bool sorted)
21
21
  : PhysicalOperator(PhysicalOperatorType::CREATE_INDEX, op.types, estimated_cardinality),
22
22
  table(table_p.Cast<DuckTableEntry>()), info(std::move(info)), unbound_expressions(std::move(unbound_expressions)),
23
23
  sorted(sorted) {
@@ -31,15 +31,15 @@ PhysicalCreateIndex::PhysicalCreateIndex(LogicalOperator &op, TableCatalogEntry
31
31
  // Sink
32
32
  //===--------------------------------------------------------------------===//
33
33
 
34
- class CreateIndexGlobalSinkState : public GlobalSinkState {
34
+ class CreateARTIndexGlobalSinkState : public GlobalSinkState {
35
35
  public:
36
36
  //! Global index to be added to the table
37
37
  unique_ptr<Index> global_index;
38
38
  };
39
39
 
40
- class CreateIndexLocalSinkState : public LocalSinkState {
40
+ class CreateARTIndexLocalSinkState : public LocalSinkState {
41
41
  public:
42
- explicit CreateIndexLocalSinkState(ClientContext &context) : arena_allocator(Allocator::Get(context)) {};
42
+ explicit CreateARTIndexLocalSinkState(ClientContext &context) : arena_allocator(Allocator::Get(context)) {};
43
43
 
44
44
  unique_ptr<Index> local_index;
45
45
  ArenaAllocator arena_allocator;
@@ -48,37 +48,26 @@ public:
48
48
  vector<column_t> key_column_ids;
49
49
  };
50
50
 
51
- unique_ptr<GlobalSinkState> PhysicalCreateIndex::GetGlobalSinkState(ClientContext &context) const {
52
- auto state = make_uniq<CreateIndexGlobalSinkState>();
51
+ unique_ptr<GlobalSinkState> PhysicalCreateARTIndex::GetGlobalSinkState(ClientContext &context) const {
52
+ auto state = make_uniq<CreateARTIndexGlobalSinkState>();
53
53
 
54
54
  // create the global index
55
- switch (info->index_type) {
56
- case IndexType::ART: {
57
- auto &storage = table.GetStorage();
58
- state->global_index = make_uniq<ART>(storage_ids, TableIOManager::Get(storage), unbound_expressions,
59
- info->constraint_type, storage.db);
60
- break;
61
- }
62
- default:
63
- throw InternalException("Unimplemented index type");
64
- }
55
+ auto &storage = table.GetStorage();
56
+ state->global_index = make_uniq<ART>(storage_ids, TableIOManager::Get(storage), unbound_expressions,
57
+ info->constraint_type, storage.db);
58
+
65
59
  return (std::move(state));
66
60
  }
67
61
 
68
- unique_ptr<LocalSinkState> PhysicalCreateIndex::GetLocalSinkState(ExecutionContext &context) const {
69
- auto state = make_uniq<CreateIndexLocalSinkState>(context.client);
62
+ unique_ptr<LocalSinkState> PhysicalCreateARTIndex::GetLocalSinkState(ExecutionContext &context) const {
63
+ auto state = make_uniq<CreateARTIndexLocalSinkState>(context.client);
70
64
 
71
65
  // create the local index
72
- switch (info->index_type) {
73
- case IndexType::ART: {
74
- auto &storage = table.GetStorage();
75
- state->local_index = make_uniq<ART>(storage_ids, TableIOManager::Get(storage), unbound_expressions,
76
- info->constraint_type, storage.db);
77
- break;
78
- }
79
- default:
80
- throw InternalException("Unimplemented index type");
81
- }
66
+
67
+ auto &storage = table.GetStorage();
68
+ state->local_index = make_uniq<ART>(storage_ids, TableIOManager::Get(storage), unbound_expressions,
69
+ info->constraint_type, storage.db);
70
+
82
71
  state->keys = vector<ARTKey>(STANDARD_VECTOR_SIZE);
83
72
  state->key_chunk.Initialize(Allocator::Get(context.client), state->local_index->logical_types);
84
73
 
@@ -88,9 +77,9 @@ unique_ptr<LocalSinkState> PhysicalCreateIndex::GetLocalSinkState(ExecutionConte
88
77
  return std::move(state);
89
78
  }
90
79
 
91
- SinkResultType PhysicalCreateIndex::SinkUnsorted(Vector &row_identifiers, OperatorSinkInput &input) const {
80
+ SinkResultType PhysicalCreateARTIndex::SinkUnsorted(Vector &row_identifiers, OperatorSinkInput &input) const {
92
81
 
93
- auto &l_state = input.local_state.Cast<CreateIndexLocalSinkState>();
82
+ auto &l_state = input.local_state.Cast<CreateARTIndexLocalSinkState>();
94
83
  auto count = l_state.key_chunk.size();
95
84
 
96
85
  // get the corresponding row IDs
@@ -108,9 +97,9 @@ SinkResultType PhysicalCreateIndex::SinkUnsorted(Vector &row_identifiers, Operat
108
97
  return SinkResultType::NEED_MORE_INPUT;
109
98
  }
110
99
 
111
- SinkResultType PhysicalCreateIndex::SinkSorted(Vector &row_identifiers, OperatorSinkInput &input) const {
100
+ SinkResultType PhysicalCreateARTIndex::SinkSorted(Vector &row_identifiers, OperatorSinkInput &input) const {
112
101
 
113
- auto &l_state = input.local_state.Cast<CreateIndexLocalSinkState>();
102
+ auto &l_state = input.local_state.Cast<CreateARTIndexLocalSinkState>();
114
103
  auto &storage = table.GetStorage();
115
104
  auto &l_index = l_state.local_index;
116
105
 
@@ -129,12 +118,13 @@ SinkResultType PhysicalCreateIndex::SinkSorted(Vector &row_identifiers, Operator
129
118
  return SinkResultType::NEED_MORE_INPUT;
130
119
  }
131
120
 
132
- SinkResultType PhysicalCreateIndex::Sink(ExecutionContext &context, DataChunk &chunk, OperatorSinkInput &input) const {
121
+ SinkResultType PhysicalCreateARTIndex::Sink(ExecutionContext &context, DataChunk &chunk,
122
+ OperatorSinkInput &input) const {
133
123
 
134
124
  D_ASSERT(chunk.ColumnCount() >= 2);
135
125
 
136
126
  // generate the keys for the given input
137
- auto &l_state = input.local_state.Cast<CreateIndexLocalSinkState>();
127
+ auto &l_state = input.local_state.Cast<CreateARTIndexLocalSinkState>();
138
128
  l_state.key_chunk.ReferenceColumns(chunk, l_state.key_column_ids);
139
129
  l_state.arena_allocator.Reset();
140
130
  ART::GenerateKeys(l_state.arena_allocator, l_state.key_chunk, l_state.keys);
@@ -147,10 +137,11 @@ SinkResultType PhysicalCreateIndex::Sink(ExecutionContext &context, DataChunk &c
147
137
  return SinkUnsorted(row_identifiers, input);
148
138
  }
149
139
 
150
- SinkCombineResultType PhysicalCreateIndex::Combine(ExecutionContext &context, OperatorSinkCombineInput &input) const {
140
+ SinkCombineResultType PhysicalCreateARTIndex::Combine(ExecutionContext &context,
141
+ OperatorSinkCombineInput &input) const {
151
142
 
152
- auto &gstate = input.global_state.Cast<CreateIndexGlobalSinkState>();
153
- auto &lstate = input.local_state.Cast<CreateIndexLocalSinkState>();
143
+ auto &gstate = input.global_state.Cast<CreateARTIndexGlobalSinkState>();
144
+ auto &lstate = input.local_state.Cast<CreateARTIndexLocalSinkState>();
154
145
 
155
146
  // merge the local index into the global index
156
147
  if (!gstate.global_index->MergeIndexes(*lstate.local_index)) {
@@ -160,11 +151,11 @@ SinkCombineResultType PhysicalCreateIndex::Combine(ExecutionContext &context, Op
160
151
  return SinkCombineResultType::FINISHED;
161
152
  }
162
153
 
163
- SinkFinalizeType PhysicalCreateIndex::Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
164
- OperatorSinkFinalizeInput &input) const {
154
+ SinkFinalizeType PhysicalCreateARTIndex::Finalize(Pipeline &pipeline, Event &event, ClientContext &context,
155
+ OperatorSinkFinalizeInput &input) const {
165
156
 
166
157
  // here, we set the resulting global index as the newly created index of the table
167
- auto &state = input.global_state.Cast<CreateIndexGlobalSinkState>();
158
+ auto &state = input.global_state.Cast<CreateARTIndexGlobalSinkState>();
168
159
 
169
160
  // vacuum excess memory and verify
170
161
  state.global_index->Vacuum();
@@ -199,8 +190,8 @@ SinkFinalizeType PhysicalCreateIndex::Finalize(Pipeline &pipeline, Event &event,
199
190
  // Source
200
191
  //===--------------------------------------------------------------------===//
201
192
 
202
- SourceResultType PhysicalCreateIndex::GetData(ExecutionContext &context, DataChunk &chunk,
203
- OperatorSourceInput &input) const {
193
+ SourceResultType PhysicalCreateARTIndex::GetData(ExecutionContext &context, DataChunk &chunk,
194
+ OperatorSourceInput &input) const {
204
195
  return SourceResultType::FINISHED;
205
196
  }
206
197
 
@@ -1,7 +1,8 @@
1
1
  #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
2
2
  #include "duckdb/execution/operator/projection/physical_projection.hpp"
3
3
  #include "duckdb/execution/operator/filter/physical_filter.hpp"
4
- #include "duckdb/execution/operator/schema/physical_create_index.hpp"
4
+ #include "duckdb/execution/operator/scan/physical_table_scan.hpp"
5
+ #include "duckdb/execution/operator/schema/physical_create_art_index.hpp"
5
6
  #include "duckdb/execution/operator/order/physical_order.hpp"
6
7
  #include "duckdb/execution/physical_plan_generator.hpp"
7
8
  #include "duckdb/planner/operator/logical_create_index.hpp"
@@ -19,7 +20,7 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalCreateInde
19
20
  auto table_scan = CreatePlan(*op.children[0]);
20
21
 
21
22
  // validate that all expressions contain valid scalar functions
22
- // e.g. get_current_timestamp(), random(), and sequence values are not allowed as ART keys
23
+ // e.g. get_current_timestamp(), random(), and sequence values are not allowed as index keys
23
24
  // because they make deletions and lookups unfeasible
24
25
  for (idx_t i = 0; i < op.unbound_expressions.size(); i++) {
25
26
  auto &expr = op.unbound_expressions[i];
@@ -29,6 +30,13 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalCreateInde
29
30
  }
30
31
  }
31
32
 
33
+ // If we get here without the plan and the index type is not ART, we throw an exception
34
+ // because we don't support any other index type yet. However an operator extension could have
35
+ // replaced this part of the plan with a different index creation operator.
36
+ if (op.info->index_type != IndexType::ART) {
37
+ throw BinderException("Index type not supported");
38
+ }
39
+
32
40
  // table scan operator for index key columns and row IDs
33
41
  dependencies.AddDependency(op.table);
34
42
 
@@ -80,8 +88,8 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalCreateInde
80
88
  // actual physical create index operator
81
89
 
82
90
  auto physical_create_index =
83
- make_uniq<PhysicalCreateIndex>(op, op.table, op.info->column_ids, std::move(op.info),
84
- std::move(op.unbound_expressions), op.estimated_cardinality, perform_sorting);
91
+ make_uniq<PhysicalCreateARTIndex>(op, op.table, op.info->column_ids, std::move(op.info),
92
+ std::move(op.unbound_expressions), op.estimated_cardinality, perform_sorting);
85
93
 
86
94
  if (perform_sorting) {
87
95
 
@@ -367,8 +367,9 @@ BoundCastInfo DefaultCasts::StringCastSwitch(BindCastInput &input, const Logical
367
367
  case LogicalTypeId::DATE:
368
368
  return BoundCastInfo(&VectorCastHelpers::TryCastErrorLoop<string_t, date_t, duckdb::TryCastErrorMessage>);
369
369
  case LogicalTypeId::TIME:
370
- case LogicalTypeId::TIME_TZ:
371
370
  return BoundCastInfo(&VectorCastHelpers::TryCastErrorLoop<string_t, dtime_t, duckdb::TryCastErrorMessage>);
371
+ case LogicalTypeId::TIME_TZ:
372
+ return BoundCastInfo(&VectorCastHelpers::TryCastErrorLoop<string_t, dtime_tz_t, duckdb::TryCastErrorMessage>);
372
373
  case LogicalTypeId::TIMESTAMP:
373
374
  case LogicalTypeId::TIMESTAMP_TZ:
374
375
  return BoundCastInfo(&VectorCastHelpers::TryCastErrorLoop<string_t, timestamp_t, duckdb::TryCastErrorMessage>);
@@ -32,7 +32,7 @@ BoundCastInfo DefaultCasts::TimeCastSwitch(BindCastInput &input, const LogicalTy
32
32
  return BoundCastInfo(&VectorCastHelpers::StringCast<dtime_t, duckdb::StringCast>);
33
33
  case LogicalTypeId::TIME_TZ:
34
34
  // time to time with time zone
35
- return ReinterpretCast;
35
+ return BoundCastInfo(&VectorCastHelpers::TemplatedCastLoop<dtime_t, dtime_tz_t, duckdb::Cast>);
36
36
  default:
37
37
  return TryVectorNullCast;
38
38
  }
@@ -44,10 +44,10 @@ BoundCastInfo DefaultCasts::TimeTzCastSwitch(BindCastInput &input, const Logical
44
44
  switch (target.id()) {
45
45
  case LogicalTypeId::VARCHAR:
46
46
  // time with time zone to varchar
47
- return BoundCastInfo(&VectorCastHelpers::StringCast<dtime_t, duckdb::StringCastTZ>);
47
+ return BoundCastInfo(&VectorCastHelpers::StringCast<dtime_tz_t, duckdb::StringCastTZ>);
48
48
  case LogicalTypeId::TIME:
49
49
  // time with time zone to time
50
- return ReinterpretCast;
50
+ return BoundCastInfo(&VectorCastHelpers::TemplatedCastLoop<dtime_tz_t, dtime_t, duckdb::Cast>);
51
51
  default:
52
52
  return TryVectorNullCast;
53
53
  }
@@ -64,9 +64,11 @@ BoundCastInfo DefaultCasts::TimestampCastSwitch(BindCastInput &input, const Logi
64
64
  // timestamp to date
65
65
  return BoundCastInfo(&VectorCastHelpers::TemplatedCastLoop<timestamp_t, date_t, duckdb::Cast>);
66
66
  case LogicalTypeId::TIME:
67
- case LogicalTypeId::TIME_TZ:
68
67
  // timestamp to time
69
68
  return BoundCastInfo(&VectorCastHelpers::TemplatedCastLoop<timestamp_t, dtime_t, duckdb::Cast>);
69
+ case LogicalTypeId::TIME_TZ:
70
+ // timestamp to time_tz
71
+ return BoundCastInfo(&VectorCastHelpers::TemplatedCastLoop<timestamp_t, dtime_tz_t, duckdb::Cast>);
70
72
  case LogicalTypeId::TIMESTAMP_TZ:
71
73
  // timestamp (us) to timestamp with time zone
72
74
  return ReinterpretCast;
@@ -96,8 +98,7 @@ BoundCastInfo DefaultCasts::TimestampTzCastSwitch(BindCastInput &input, const Lo
96
98
  return BoundCastInfo(&VectorCastHelpers::StringCast<timestamp_t, duckdb::StringCastTZ>);
97
99
  case LogicalTypeId::TIME_TZ:
98
100
  // timestamp with time zone to time with time zone.
99
- // TODO: set the offset to +00
100
- return BoundCastInfo(&VectorCastHelpers::TemplatedCastLoop<timestamp_t, dtime_t, duckdb::Cast>);
101
+ return BoundCastInfo(&VectorCastHelpers::TemplatedCastLoop<timestamp_t, dtime_tz_t, duckdb::Cast>);
101
102
  case LogicalTypeId::TIMESTAMP:
102
103
  // timestamp with time zone to timestamp (us)
103
104
  return ReinterpretCast;
@@ -1,8 +1,8 @@
1
1
  #ifndef DUCKDB_VERSION
2
- #define DUCKDB_VERSION "0.8.2-dev3250"
2
+ #define DUCKDB_VERSION "0.8.2-dev3300"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "a7f85b3b2c"
5
+ #define DUCKDB_SOURCE_ID "26931f7ac6"
6
6
  #endif
7
7
  #include "duckdb/function/table/system_functions.hpp"
8
8
  #include "duckdb/main/database.hpp"
@@ -31,6 +31,7 @@ public:
31
31
  string sql;
32
32
  vector<unique_ptr<ParsedExpression>> expressions;
33
33
  vector<unique_ptr<ParsedExpression>> parsed_expressions;
34
+ case_insensitive_map_t<Value> options;
34
35
 
35
36
  public:
36
37
  unique_ptr<CreateInfo> GetInfo() const override;
@@ -16,8 +16,9 @@ namespace duckdb {
16
16
  // Index Types
17
17
  //===--------------------------------------------------------------------===//
18
18
  enum class IndexType : uint8_t {
19
- INVALID = 0, // invalid index type
20
- ART = 1 // Adaptive Radix Tree
19
+ INVALID = 0, // invalid index type
20
+ ART = 1, // Adaptive Radix Tree
21
+ EXTENSION = 100 // Extension index
21
22
  };
22
23
 
23
24
  //===--------------------------------------------------------------------===//
@@ -73,7 +73,7 @@ struct Cast {
73
73
  };
74
74
 
75
75
  struct HandleCastError {
76
- static void AssignError(string error_message, string *error_message_ptr) {
76
+ static void AssignError(const string &error_message, string *error_message_ptr) {
77
77
  if (!error_message_ptr) {
78
78
  throw ConversionException(error_message);
79
79
  }
@@ -470,6 +470,16 @@ DUCKDB_API bool TryCast::Operation(date_t input, timestamp_t &result, bool stric
470
470
  //===--------------------------------------------------------------------===//
471
471
  template <>
472
472
  DUCKDB_API bool TryCast::Operation(dtime_t input, dtime_t &result, bool strict);
473
+ template <>
474
+ DUCKDB_API bool TryCast::Operation(dtime_t input, dtime_tz_t &result, bool strict);
475
+
476
+ //===--------------------------------------------------------------------===//
477
+ // Time With Time Zone Casts (Offset)
478
+ //===--------------------------------------------------------------------===//
479
+ template <>
480
+ DUCKDB_API bool TryCast::Operation(dtime_tz_t input, dtime_t &result, bool strict);
481
+ template <>
482
+ DUCKDB_API bool TryCast::Operation(dtime_tz_t input, dtime_tz_t &result, bool strict);
473
483
 
474
484
  //===--------------------------------------------------------------------===//
475
485
  // Timestamp Casts
@@ -479,6 +489,8 @@ DUCKDB_API bool TryCast::Operation(timestamp_t input, date_t &result, bool stric
479
489
  template <>
480
490
  DUCKDB_API bool TryCast::Operation(timestamp_t input, dtime_t &result, bool strict);
481
491
  template <>
492
+ DUCKDB_API bool TryCast::Operation(timestamp_t input, dtime_tz_t &result, bool strict);
493
+ template <>
482
494
  DUCKDB_API bool TryCast::Operation(timestamp_t input, timestamp_t &result, bool strict);
483
495
 
484
496
  //===--------------------------------------------------------------------===//
@@ -506,6 +518,15 @@ DUCKDB_API bool TryCast::Operation(string_t input, dtime_t &result, bool strict)
506
518
  template <>
507
519
  dtime_t Cast::Operation(string_t input);
508
520
  //===--------------------------------------------------------------------===//
521
+ // String -> TimeTZ Casts
522
+ //===--------------------------------------------------------------------===//
523
+ template <>
524
+ DUCKDB_API bool TryCastErrorMessage::Operation(string_t input, dtime_tz_t &result, string *error_message, bool strict);
525
+ template <>
526
+ DUCKDB_API bool TryCast::Operation(string_t input, dtime_tz_t &result, bool strict);
527
+ template <>
528
+ dtime_tz_t Cast::Operation(string_t input);
529
+ //===--------------------------------------------------------------------===//
509
530
  // String -> Timestamp Casts
510
531
  //===--------------------------------------------------------------------===//
511
532
  template <>
@@ -71,7 +71,7 @@ struct StringCastTZ {
71
71
  template <>
72
72
  duckdb::string_t StringCastTZ::Operation(date_t input, Vector &result);
73
73
  template <>
74
- duckdb::string_t StringCastTZ::Operation(dtime_t input, Vector &result);
74
+ duckdb::string_t StringCastTZ::Operation(dtime_tz_t input, Vector &result);
75
75
  template <>
76
76
  duckdb::string_t StringCastTZ::Operation(timestamp_t input, Vector &result);
77
77
 
@@ -81,12 +81,54 @@ struct dtime_t { // NOLINT
81
81
  };
82
82
 
83
83
  // special values
84
- static inline dtime_t allballs() {
84
+ static inline dtime_t allballs() { // NOLINT
85
85
  return dtime_t(0);
86
86
  } // NOLINT
87
87
  };
88
88
 
89
- struct dtime_tz_t : public dtime_t {};
89
+ struct dtime_tz_t { // NOLINT
90
+ static constexpr const int TIME_BITS = 40;
91
+ static constexpr const int OFFSET_BITS = 24;
92
+ static constexpr const uint64_t OFFSET_MASK = ~uint64_t(0) >> TIME_BITS;
93
+ static constexpr const int32_t MAX_OFFSET = 1559 * 60 * 60;
94
+ static constexpr const int32_t MIN_OFFSET = -MAX_OFFSET;
95
+
96
+ uint64_t bits;
97
+
98
+ dtime_tz_t() = default;
99
+
100
+ inline dtime_tz_t(dtime_t t, int32_t offset)
101
+ : bits((uint64_t(t.micros) << OFFSET_BITS) | uint64_t(offset + MAX_OFFSET)) {
102
+ }
103
+
104
+ inline dtime_t time() const { // NOLINT
105
+ return dtime_t(bits >> OFFSET_BITS);
106
+ }
107
+
108
+ inline int32_t offset() const { // NOLINT
109
+ return int32_t(bits & OFFSET_MASK) - MAX_OFFSET;
110
+ }
111
+
112
+ // comparison operators
113
+ inline bool operator==(const dtime_tz_t &rhs) const {
114
+ return bits == rhs.bits;
115
+ };
116
+ inline bool operator!=(const dtime_tz_t &rhs) const {
117
+ return bits != rhs.bits;
118
+ };
119
+ inline bool operator<=(const dtime_tz_t &rhs) const {
120
+ return bits <= rhs.bits;
121
+ };
122
+ inline bool operator<(const dtime_tz_t &rhs) const {
123
+ return bits < rhs.bits;
124
+ };
125
+ inline bool operator>(const dtime_tz_t &rhs) const {
126
+ return bits > rhs.bits;
127
+ };
128
+ inline bool operator>=(const dtime_tz_t &rhs) const {
129
+ return bits >= rhs.bits;
130
+ };
131
+ };
90
132
 
91
133
  } // namespace duckdb
92
134
 
@@ -100,11 +142,12 @@ struct hash<duckdb::dtime_t> {
100
142
  return hash<int64_t>()((int64_t)k);
101
143
  }
102
144
  };
145
+
103
146
  template <>
104
147
  struct hash<duckdb::dtime_tz_t> {
105
148
  std::size_t operator()(const duckdb::dtime_tz_t &k) const {
106
149
  using std::hash;
107
- return hash<int64_t>()((int64_t)k);
150
+ return hash<int64_t>()(k.bits);
108
151
  }
109
152
  };
110
153
  } // namespace std
@@ -15,6 +15,7 @@
15
15
  namespace duckdb {
16
16
 
17
17
  struct dtime_t;
18
+ struct dtime_tz_t;
18
19
 
19
20
  //! The Time class is a static class that holds helper functions for the Time
20
21
  //! type.
@@ -24,6 +25,10 @@ public:
24
25
  DUCKDB_API static dtime_t FromString(const string &str, bool strict = false);
25
26
  DUCKDB_API static dtime_t FromCString(const char *buf, idx_t len, bool strict = false);
26
27
  DUCKDB_API static bool TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict = false);
28
+ DUCKDB_API static bool TryConvertTimeTZ(const char *buf, idx_t len, idx_t &pos, dtime_tz_t &result,
29
+ bool strict = false);
30
+ //! Format is ±[HH]HH[:MM[:SS]]
31
+ DUCKDB_API static bool TryParseUTCOffset(const char *str, idx_t &pos, idx_t len, int32_t &offset);
27
32
 
28
33
  //! Convert a time object to a string in the format "hh:mm:ss"
29
34
  DUCKDB_API static string ToString(dtime_t time);
@@ -120,7 +120,7 @@ public:
120
120
  DUCKDB_API static Value DATE(int32_t year, int32_t month, int32_t day);
121
121
  //! Create a time Value from a specified time
122
122
  DUCKDB_API static Value TIME(dtime_t time);
123
- DUCKDB_API static Value TIMETZ(dtime_t time);
123
+ DUCKDB_API static Value TIMETZ(dtime_tz_t time);
124
124
  //! Create a time Value from a specified time
125
125
  DUCKDB_API static Value TIME(int32_t hour, int32_t min, int32_t sec, int32_t micros);
126
126
  //! Create a timestamp Value from a specified date/time combination
@@ -302,6 +302,7 @@ private:
302
302
  uint64_t hash;
303
303
  date_t date;
304
304
  dtime_t time;
305
+ dtime_tz_t timetz;
305
306
  timestamp_t timestamp;
306
307
  interval_t interval;
307
308
  } value_; // NOLINT
@@ -1,7 +1,7 @@
1
1
  //===----------------------------------------------------------------------===//
2
2
  // DuckDB
3
3
  //
4
- // duckdb/execution/operator/schema/physical_create_index.hpp
4
+ // duckdb/execution/operator/schema/physical_create_art_index.hpp
5
5
  //
6
6
  //
7
7
  //===----------------------------------------------------------------------===//
@@ -20,14 +20,14 @@ namespace duckdb {
20
20
  class DuckTableEntry;
21
21
 
22
22
  //! Physical CREATE (UNIQUE) INDEX statement
23
- class PhysicalCreateIndex : public PhysicalOperator {
23
+ class PhysicalCreateARTIndex : public PhysicalOperator {
24
24
  public:
25
25
  static constexpr const PhysicalOperatorType TYPE = PhysicalOperatorType::CREATE_INDEX;
26
26
 
27
27
  public:
28
- PhysicalCreateIndex(LogicalOperator &op, TableCatalogEntry &table, const vector<column_t> &column_ids,
29
- unique_ptr<CreateIndexInfo> info, vector<unique_ptr<Expression>> unbound_expressions,
30
- idx_t estimated_cardinality, const bool sorted);
28
+ PhysicalCreateARTIndex(LogicalOperator &op, TableCatalogEntry &table, const vector<column_t> &column_ids,
29
+ unique_ptr<CreateIndexInfo> info, vector<unique_ptr<Expression>> unbound_expressions,
30
+ idx_t estimated_cardinality, const bool sorted);
31
31
 
32
32
  //! The table to create the index for
33
33
  DuckTableEntry &table;
@@ -99,13 +99,16 @@ typedef void (*copy_flush_batch_t)(ClientContext &context, FunctionData &bind_da
99
99
  PreparedBatchData &batch);
100
100
  typedef idx_t (*copy_desired_batch_size_t)(ClientContext &context, FunctionData &bind_data);
101
101
 
102
+ typedef bool (*copy_supports_type_t)(const LogicalType &type);
103
+
102
104
  class CopyFunction : public Function {
103
105
  public:
104
106
  explicit CopyFunction(string name)
105
107
  : Function(name), plan(nullptr), copy_to_bind(nullptr), copy_to_initialize_local(nullptr),
106
108
  copy_to_initialize_global(nullptr), copy_to_sink(nullptr), copy_to_combine(nullptr),
107
109
  copy_to_finalize(nullptr), execution_mode(nullptr), prepare_batch(nullptr), flush_batch(nullptr),
108
- desired_batch_size(nullptr), serialize(nullptr), deserialize(nullptr), copy_from_bind(nullptr) {
110
+ desired_batch_size(nullptr), serialize(nullptr), deserialize(nullptr), supports_type(nullptr),
111
+ copy_from_bind(nullptr) {
109
112
  }
110
113
 
111
114
  //! Plan rewrite copy function
@@ -126,6 +129,8 @@ public:
126
129
  copy_to_serialize_t serialize;
127
130
  copy_to_deserialize_t deserialize;
128
131
 
132
+ copy_supports_type_t supports_type;
133
+
129
134
  copy_from_bind_t copy_from_bind;
130
135
  TableFunction copy_from_function;
131
136
 
@@ -318,8 +318,9 @@ private:
318
318
  case LogicalTypeId::DATE:
319
319
  return std::is_same<T, date_t>();
320
320
  case LogicalTypeId::TIME:
321
- case LogicalTypeId::TIME_TZ:
322
321
  return std::is_same<T, dtime_t>();
322
+ case LogicalTypeId::TIME_TZ:
323
+ return std::is_same<T, dtime_tz_t>();
323
324
  case LogicalTypeId::TIMESTAMP:
324
325
  case LogicalTypeId::TIMESTAMP_MS:
325
326
  case LogicalTypeId::TIMESTAMP_NS:
@@ -25,6 +25,8 @@ struct CreateIndexInfo : public CreateInfo {
25
25
  IndexType index_type;
26
26
  //! Name of the Index
27
27
  string index_name;
28
+ //! Name of the Index type
29
+ string index_type_name;
28
30
  //! Index Constraint Type
29
31
  IndexConstraintType constraint_type;
30
32
  //! The table to create the index on
@@ -40,6 +42,9 @@ struct CreateIndexInfo : public CreateInfo {
40
42
  //! Column IDs needed for index creation
41
43
  vector<column_t> column_ids;
42
44
 
45
+ //! Options values (WITH ...)
46
+ case_insensitive_map_t<Value> options;
47
+
43
48
  protected:
44
49
  void SerializeInternal(Serializer &serializer) const override;
45
50
 
@@ -13,6 +13,8 @@
13
13
 
14
14
  namespace duckdb {
15
15
 
16
+ class ColumnBindingResolver;
17
+
16
18
  struct LogicalExtensionOperator : public LogicalOperator {
17
19
  public:
18
20
  static constexpr const LogicalOperatorType TYPE = LogicalOperatorType::LOGICAL_EXTENSION_OPERATOR;
@@ -31,6 +33,7 @@ public:
31
33
 
32
34
  virtual unique_ptr<PhysicalOperator> CreatePlan(ClientContext &context, PhysicalPlanGenerator &generator) = 0;
33
35
 
36
+ virtual void ResolveColumnBindings(ColumnBindingResolver &res, vector<ColumnBinding> &bindings);
34
37
  virtual string GetExtensionName() const;
35
38
  };
36
39
  } // namespace duckdb
@@ -125,7 +125,7 @@ public:
125
125
  void UpdateColumn(TableCatalogEntry &table, ClientContext &context, Vector &row_ids,
126
126
  const vector<column_t> &column_path, DataChunk &updates);
127
127
 
128
- //! Add an index to the DataTable. NOTE: for CREATE (UNIQUE) INDEX statements, we use the PhysicalCreateIndex
128
+ //! Add an index to the DataTable. NOTE: for CREATE (UNIQUE) INDEX statements, we use the PhysicalCreateARTIndex
129
129
  //! operator. This function is only used during the WAL replay, and is a much less performant index creation
130
130
  //! approach.
131
131
  void WALAddIndex(ClientContext &context, unique_ptr<Index> index,
@@ -184,9 +184,11 @@ void BaseAppender::AppendValueInternal(T input) {
184
184
  AppendValueInternal<T, timestamp_t>(col, input);
185
185
  break;
186
186
  case LogicalTypeId::TIME:
187
- case LogicalTypeId::TIME_TZ:
188
187
  AppendValueInternal<T, dtime_t>(col, input);
189
188
  break;
189
+ case LogicalTypeId::TIME_TZ:
190
+ AppendValueInternal<T, dtime_tz_t>(col, input);
191
+ break;
190
192
  case LogicalTypeId::INTERVAL:
191
193
  AppendValueInternal<T, interval_t>(col, input);
192
194
  break;
@@ -182,9 +182,11 @@ duckdb_state deprecated_duckdb_translate_column(MaterializedQueryResult &result,
182
182
  WriteData<date_t>(column, collection, column_ids);
183
183
  break;
184
184
  case LogicalTypeId::TIME:
185
- case LogicalTypeId::TIME_TZ:
186
185
  WriteData<dtime_t>(column, collection, column_ids);
187
186
  break;
187
+ case LogicalTypeId::TIME_TZ:
188
+ WriteData<dtime_tz_t>(column, collection, column_ids);
189
+ break;
188
190
  case LogicalTypeId::TIMESTAMP:
189
191
  case LogicalTypeId::TIMESTAMP_TZ:
190
192
  WriteData<timestamp_t>(column, collection, column_ids);
@@ -22,6 +22,7 @@ unique_ptr<CreateInfo> CreateIndexInfo::Copy() const {
22
22
  result->scan_types = scan_types;
23
23
  result->names = names;
24
24
  result->column_ids = column_ids;
25
+ result->options = options;
25
26
  return std::move(result);
26
27
  }
27
28
 
@@ -37,6 +38,12 @@ void CreateIndexInfo::SerializeInternal(Serializer &serializer) const {
37
38
  writer.WriteRegularSerializableList(scan_types);
38
39
  writer.WriteList<string>(names);
39
40
  writer.WriteList<column_t>(column_ids);
41
+ writer.WriteString(index_type_name);
42
+ writer.WriteField((idx_t)options.size());
43
+ for (auto &kv : options) {
44
+ writer.WriteString(kv.first);
45
+ writer.WriteSerializable(kv.second);
46
+ }
40
47
  writer.Finalize();
41
48
  }
42
49
 
@@ -55,6 +62,13 @@ unique_ptr<CreateIndexInfo> CreateIndexInfo::Deserialize(Deserializer &deseriali
55
62
  result->scan_types = reader.ReadRequiredSerializableList<LogicalType, LogicalType>();
56
63
  result->names = reader.ReadRequiredList<string>();
57
64
  result->column_ids = reader.ReadRequiredList<column_t>();
65
+ result->index_type_name = reader.ReadRequired<string>();
66
+ auto options_count = reader.ReadRequired<idx_t>();
67
+ for (idx_t i = 0; i < options_count; i++) {
68
+ auto key = reader.ReadRequired<string>();
69
+ auto value = reader.ReadRequiredSerializable<Value, Value>();
70
+ result->options[key] = value;
71
+ }
58
72
  reader.Finalize();
59
73
  return result;
60
74
  }