duckdb 0.7.1-dev37.0 → 0.7.1-dev415.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.
- package/README.md +1 -1
- package/binding.gyp +7 -7
- package/package.json +3 -3
- package/src/duckdb/extension/json/buffered_json_reader.cpp +50 -9
- package/src/duckdb/extension/json/include/buffered_json_reader.hpp +7 -2
- package/src/duckdb/extension/json/include/json_scan.hpp +45 -10
- package/src/duckdb/extension/json/json_functions/copy_json.cpp +35 -22
- package/src/duckdb/extension/json/json_functions/json_create.cpp +8 -8
- package/src/duckdb/extension/json/json_functions/json_structure.cpp +8 -3
- package/src/duckdb/extension/json/json_functions/json_transform.cpp +54 -10
- package/src/duckdb/extension/json/json_functions/read_json.cpp +104 -49
- package/src/duckdb/extension/json/json_functions/read_json_objects.cpp +5 -3
- package/src/duckdb/extension/json/json_functions.cpp +7 -0
- package/src/duckdb/extension/json/json_scan.cpp +144 -37
- package/src/duckdb/extension/parquet/column_reader.cpp +7 -0
- package/src/duckdb/extension/parquet/include/column_reader.hpp +1 -0
- package/src/duckdb/extension/parquet/parquet-extension.cpp +2 -9
- package/src/duckdb/src/catalog/catalog.cpp +62 -13
- package/src/duckdb/src/catalog/catalog_entry/index_catalog_entry.cpp +8 -7
- package/src/duckdb/src/catalog/catalog_entry/schema_catalog_entry.cpp +1 -1
- package/src/duckdb/src/catalog/catalog_set.cpp +1 -1
- package/src/duckdb/src/catalog/default/default_views.cpp +1 -1
- package/src/duckdb/src/common/bind_helpers.cpp +55 -0
- package/src/duckdb/src/common/enums/logical_operator_type.cpp +2 -0
- package/src/duckdb/src/common/enums/physical_operator_type.cpp +2 -0
- package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
- package/src/duckdb/src/common/file_system.cpp +28 -0
- package/src/duckdb/src/common/hive_partitioning.cpp +1 -0
- package/src/duckdb/src/common/local_file_system.cpp +4 -4
- package/src/duckdb/src/common/operator/cast_operators.cpp +10 -4
- package/src/duckdb/src/common/string_util.cpp +8 -4
- package/src/duckdb/src/common/types/partitioned_column_data.cpp +1 -0
- package/src/duckdb/src/common/types/time.cpp +1 -1
- package/src/duckdb/src/common/types/timestamp.cpp +35 -4
- package/src/duckdb/src/common/types.cpp +37 -11
- package/src/duckdb/src/execution/column_binding_resolver.cpp +5 -2
- package/src/duckdb/src/execution/index/art/art.cpp +117 -67
- package/src/duckdb/src/execution/index/art/art_key.cpp +24 -12
- package/src/duckdb/src/execution/index/art/leaf.cpp +7 -8
- package/src/duckdb/src/execution/index/art/node.cpp +13 -27
- package/src/duckdb/src/execution/index/art/node16.cpp +5 -8
- package/src/duckdb/src/execution/index/art/node256.cpp +3 -5
- package/src/duckdb/src/execution/index/art/node4.cpp +4 -7
- package/src/duckdb/src/execution/index/art/node48.cpp +5 -8
- package/src/duckdb/src/execution/index/art/prefix.cpp +2 -3
- package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +6 -27
- package/src/duckdb/src/execution/operator/helper/physical_reset.cpp +1 -9
- package/src/duckdb/src/execution/operator/helper/physical_set.cpp +1 -9
- package/src/duckdb/src/execution/operator/join/physical_iejoin.cpp +7 -9
- package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +6 -11
- package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +13 -13
- package/src/duckdb/src/execution/operator/schema/physical_detach.cpp +37 -0
- package/src/duckdb/src/execution/operator/schema/physical_drop.cpp +0 -5
- package/src/duckdb/src/execution/physical_operator.cpp +6 -6
- package/src/duckdb/src/execution/physical_plan/plan_simple.cpp +4 -0
- package/src/duckdb/src/execution/physical_plan_generator.cpp +1 -0
- package/src/duckdb/src/function/pragma/pragma_queries.cpp +38 -11
- package/src/duckdb/src/function/scalar/generic/current_setting.cpp +2 -2
- package/src/duckdb/src/function/scalar/map/map.cpp +69 -21
- package/src/duckdb/src/function/table/read_csv.cpp +17 -5
- package/src/duckdb/src/function/table/system/duckdb_temporary_files.cpp +59 -0
- package/src/duckdb/src/function/table/system_functions.cpp +1 -0
- package/src/duckdb/src/function/table/table_scan.cpp +3 -0
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +7 -1
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp +1 -1
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry/index_catalog_entry.hpp +1 -1
- package/src/duckdb/src/include/duckdb/common/bind_helpers.hpp +2 -0
- package/src/duckdb/src/include/duckdb/common/enums/logical_operator_type.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +3 -2
- package/src/duckdb/src/include/duckdb/common/enums/wal_type.hpp +3 -0
- package/src/duckdb/src/include/duckdb/common/exception.hpp +10 -0
- package/src/duckdb/src/include/duckdb/common/file_system.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/hive_partitioning.hpp +9 -1
- package/src/duckdb/src/include/duckdb/common/radix_partitioning.hpp +4 -4
- package/src/duckdb/src/include/duckdb/common/string_util.hpp +9 -2
- package/src/duckdb/src/include/duckdb/common/types/timestamp.hpp +5 -1
- package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +37 -41
- package/src/duckdb/src/include/duckdb/execution/index/art/art_key.hpp +8 -11
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/base_csv_reader.hpp +1 -3
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/buffered_csv_reader.hpp +0 -2
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +2 -0
- package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_detach.hpp +32 -0
- package/src/duckdb/src/include/duckdb/function/table/system_functions.hpp +4 -0
- package/src/duckdb/src/include/duckdb/main/client_data.hpp +2 -2
- package/src/duckdb/src/include/duckdb/main/config.hpp +2 -3
- package/src/duckdb/src/include/duckdb/main/{extension_functions.hpp → extension_entries.hpp} +26 -5
- package/src/duckdb/src/include/duckdb/main/extension_helper.hpp +3 -0
- package/src/duckdb/src/include/duckdb/main/settings.hpp +9 -0
- package/src/duckdb/src/include/duckdb/parallel/pipeline_executor.hpp +0 -7
- package/src/duckdb/src/include/duckdb/parser/parsed_data/create_database_info.hpp +0 -4
- package/src/duckdb/src/include/duckdb/parser/parsed_data/detach_info.hpp +32 -0
- package/src/duckdb/src/include/duckdb/parser/query_node/select_node.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/sql_statement.hpp +2 -2
- package/src/duckdb/src/include/duckdb/parser/statement/copy_statement.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/statement/detach_statement.hpp +29 -0
- package/src/duckdb/src/include/duckdb/parser/statement/list.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/statement/select_statement.hpp +3 -3
- package/src/duckdb/src/include/duckdb/parser/tableref/subqueryref.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/tokens.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +1 -0
- package/src/duckdb/src/include/duckdb/planner/binder.hpp +4 -0
- package/src/duckdb/src/include/duckdb/planner/expression_binder/index_binder.hpp +10 -3
- package/src/duckdb/src/include/duckdb/planner/operator/logical_execute.hpp +1 -5
- package/src/duckdb/src/include/duckdb/planner/operator/logical_show.hpp +1 -2
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +8 -0
- package/src/duckdb/src/include/duckdb/storage/data_table.hpp +7 -1
- package/src/duckdb/src/include/duckdb/storage/index.hpp +47 -38
- package/src/duckdb/src/include/duckdb/storage/storage_extension.hpp +7 -0
- package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/write_ahead_log.hpp +7 -0
- package/src/duckdb/src/main/client_context.cpp +2 -0
- package/src/duckdb/src/main/config.cpp +1 -0
- package/src/duckdb/src/main/database.cpp +14 -5
- package/src/duckdb/src/main/extension/extension_alias.cpp +2 -1
- package/src/duckdb/src/main/extension/extension_install.cpp +43 -9
- package/src/duckdb/src/main/extension/extension_load.cpp +29 -5
- package/src/duckdb/src/main/settings/settings.cpp +16 -0
- package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +2 -6
- package/src/duckdb/src/parallel/pipeline_executor.cpp +1 -55
- package/src/duckdb/src/parser/parsed_data/create_index_info.cpp +3 -0
- package/src/duckdb/src/parser/statement/copy_statement.cpp +2 -13
- package/src/duckdb/src/parser/statement/delete_statement.cpp +3 -0
- package/src/duckdb/src/parser/statement/detach_statement.cpp +15 -0
- package/src/duckdb/src/parser/statement/insert_statement.cpp +9 -0
- package/src/duckdb/src/parser/statement/update_statement.cpp +3 -0
- package/src/duckdb/src/parser/transform/expression/transform_case.cpp +3 -3
- package/src/duckdb/src/parser/transform/statement/transform_create_database.cpp +0 -1
- package/src/duckdb/src/parser/transform/statement/transform_detach.cpp +19 -0
- package/src/duckdb/src/parser/transformer.cpp +2 -0
- package/src/duckdb/src/planner/bind_context.cpp +1 -1
- package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +3 -0
- package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +7 -14
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +16 -14
- package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +13 -0
- package/src/duckdb/src/planner/binder/statement/bind_detach.cpp +19 -0
- package/src/duckdb/src/planner/binder/statement/bind_drop.cpp +29 -4
- package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +22 -1
- package/src/duckdb/src/planner/binder.cpp +2 -0
- package/src/duckdb/src/planner/expression_binder/index_binder.cpp +32 -1
- package/src/duckdb/src/planner/logical_operator.cpp +6 -1
- package/src/duckdb/src/planner/planner.cpp +1 -0
- package/src/duckdb/src/storage/buffer_manager.cpp +105 -26
- package/src/duckdb/src/storage/compression/bitpacking.cpp +16 -7
- package/src/duckdb/src/storage/data_table.cpp +66 -3
- package/src/duckdb/src/storage/index.cpp +1 -1
- package/src/duckdb/src/storage/local_storage.cpp +1 -1
- package/src/duckdb/src/storage/table/column_data.cpp +4 -2
- package/src/duckdb/src/storage/table/update_segment.cpp +15 -0
- package/src/duckdb/src/storage/table_index_list.cpp +1 -2
- package/src/duckdb/src/storage/wal_replay.cpp +68 -0
- package/src/duckdb/src/storage/write_ahead_log.cpp +21 -1
- package/src/duckdb/src/transaction/commit_state.cpp +5 -2
- package/src/duckdb/third_party/concurrentqueue/blockingconcurrentqueue.h +2 -2
- package/src/duckdb/third_party/fmt/include/fmt/core.h +1 -2
- package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +1 -0
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +14 -0
- package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +530 -1006
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +17659 -17626
- package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +4 -4
- package/src/duckdb/ub_src_execution_operator_schema.cpp +2 -0
- package/src/duckdb/ub_src_function_table_system.cpp +2 -0
- package/src/duckdb/ub_src_parser_statement.cpp +2 -0
- package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
- package/src/duckdb/ub_src_planner_binder_statement.cpp +2 -0
- package/src/statement.cpp +46 -12
- package/test/arrow.test.ts +3 -3
- package/test/prepare.test.ts +39 -1
- package/test/typescript_decls.test.ts +1 -1
- package/src/duckdb/src/include/duckdb/function/create_database_extension.hpp +0 -37
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include "duckdb/common/exception.hpp"
|
|
5
5
|
#include "duckdb/common/types/value.hpp"
|
|
6
6
|
#include "duckdb/common/case_insensitive_map.hpp"
|
|
7
|
+
#include <numeric>
|
|
7
8
|
|
|
8
9
|
namespace duckdb {
|
|
9
10
|
|
|
@@ -64,4 +65,58 @@ vector<bool> ParseColumnList(const Value &value, vector<string> &names, const st
|
|
|
64
65
|
return ParseColumnList(children, names, loption);
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
vector<idx_t> ParseColumnsOrdered(const vector<Value> &set, vector<string> &names, const string &loption) {
|
|
69
|
+
vector<idx_t> result;
|
|
70
|
+
|
|
71
|
+
if (set.empty()) {
|
|
72
|
+
throw BinderException("\"%s\" expects a column list or * as parameter", loption);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Maps option to bool indicating if its found and the index in the original set
|
|
76
|
+
case_insensitive_map_t<std::pair<bool, idx_t>> option_map;
|
|
77
|
+
for (idx_t i = 0; i < set.size(); i++) {
|
|
78
|
+
option_map[set[i].ToString()] = {false, i};
|
|
79
|
+
}
|
|
80
|
+
result.resize(option_map.size());
|
|
81
|
+
|
|
82
|
+
for (idx_t i = 0; i < names.size(); i++) {
|
|
83
|
+
auto entry = option_map.find(names[i]);
|
|
84
|
+
if (entry != option_map.end()) {
|
|
85
|
+
result[entry->second.second] = i;
|
|
86
|
+
entry->second.first = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (auto &entry : option_map) {
|
|
90
|
+
if (!entry.second.first) {
|
|
91
|
+
throw BinderException("\"%s\" expected to find %s, but it was not found in the table", loption,
|
|
92
|
+
entry.first.c_str());
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
vector<idx_t> ParseColumnsOrdered(const Value &value, vector<string> &names, const string &loption) {
|
|
99
|
+
vector<idx_t> result;
|
|
100
|
+
|
|
101
|
+
// Only accept a list of arguments
|
|
102
|
+
if (value.type().id() != LogicalTypeId::LIST) {
|
|
103
|
+
// Support a single argument if it's '*'
|
|
104
|
+
if (value.type().id() == LogicalTypeId::VARCHAR && value.GetValue<string>() == "*") {
|
|
105
|
+
result.resize(names.size(), 0);
|
|
106
|
+
std::iota(std::begin(result), std::end(result), 0);
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
throw BinderException("\"%s\" expects a column list or * as parameter", loption);
|
|
110
|
+
}
|
|
111
|
+
auto &children = ListValue::GetChildren(value);
|
|
112
|
+
// accept '*' as single argument
|
|
113
|
+
if (children.size() == 1 && children[0].type().id() == LogicalTypeId::VARCHAR &&
|
|
114
|
+
children[0].GetValue<string>() == "*") {
|
|
115
|
+
result.resize(names.size(), 0);
|
|
116
|
+
std::iota(std::begin(result), std::end(result), 0);
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
return ParseColumnsOrdered(children, names, loption);
|
|
120
|
+
}
|
|
121
|
+
|
|
67
122
|
} // namespace duckdb
|
|
@@ -100,6 +100,8 @@ string LogicalOperatorToString(LogicalOperatorType type) {
|
|
|
100
100
|
return "CREATE_SCHEMA";
|
|
101
101
|
case LogicalOperatorType::LOGICAL_ATTACH:
|
|
102
102
|
return "ATTACH";
|
|
103
|
+
case LogicalOperatorType::LOGICAL_DETACH:
|
|
104
|
+
return "ATTACH";
|
|
103
105
|
case LogicalOperatorType::LOGICAL_DROP:
|
|
104
106
|
return "DROP";
|
|
105
107
|
case LogicalOperatorType::LOGICAL_PRAGMA:
|
|
@@ -133,6 +133,8 @@ string PhysicalOperatorToString(PhysicalOperatorType type) {
|
|
|
133
133
|
return "CREATE_TYPE";
|
|
134
134
|
case PhysicalOperatorType::ATTACH:
|
|
135
135
|
return "ATTACH";
|
|
136
|
+
case PhysicalOperatorType::DETACH:
|
|
137
|
+
return "DETACH";
|
|
136
138
|
case PhysicalOperatorType::RESULT_COLLECTOR:
|
|
137
139
|
return "RESULT_COLLECTOR";
|
|
138
140
|
case PhysicalOperatorType::EXTENSION:
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "duckdb/main/client_context.hpp"
|
|
11
11
|
#include "duckdb/main/client_data.hpp"
|
|
12
12
|
#include "duckdb/main/database.hpp"
|
|
13
|
+
#include "duckdb/main/extension_helper.hpp"
|
|
13
14
|
|
|
14
15
|
#include <cstdint>
|
|
15
16
|
#include <cstdio>
|
|
@@ -335,6 +336,33 @@ bool FileSystem::CanHandleFile(const string &fpath) {
|
|
|
335
336
|
throw NotImplementedException("%s: CanHandleFile is not implemented!", GetName());
|
|
336
337
|
}
|
|
337
338
|
|
|
339
|
+
vector<string> FileSystem::GlobFiles(const string &pattern, ClientContext &context) {
|
|
340
|
+
auto result = Glob(pattern, context);
|
|
341
|
+
if (result.empty()) {
|
|
342
|
+
string required_extension;
|
|
343
|
+
const string prefixes[] = {"http://", "https://", "s3://"};
|
|
344
|
+
for (auto &prefix : prefixes) {
|
|
345
|
+
if (StringUtil::StartsWith(pattern, prefix)) {
|
|
346
|
+
required_extension = "httpfs";
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (!required_extension.empty() && !context.db->ExtensionIsLoaded(required_extension)) {
|
|
351
|
+
// an extension is required to read this file but it is not loaded - try to load it
|
|
352
|
+
ExtensionHelper::LoadExternalExtension(context, required_extension);
|
|
353
|
+
// success! glob again
|
|
354
|
+
// check the extension is loaded just in case to prevent an infinite loop here
|
|
355
|
+
if (!context.db->ExtensionIsLoaded(required_extension)) {
|
|
356
|
+
throw InternalException("Extension load \"%s\" did not throw but somehow the extension was not loaded",
|
|
357
|
+
required_extension);
|
|
358
|
+
}
|
|
359
|
+
return GlobFiles(pattern, context);
|
|
360
|
+
}
|
|
361
|
+
throw IOException("No files found that match the pattern \"%s\"", pattern);
|
|
362
|
+
}
|
|
363
|
+
return result;
|
|
364
|
+
}
|
|
365
|
+
|
|
338
366
|
void FileSystem::Seek(FileHandle &handle, idx_t location) {
|
|
339
367
|
throw NotImplementedException("%s: Seek is not implemented!", GetName());
|
|
340
368
|
}
|
|
@@ -150,6 +150,7 @@ HivePartitionedColumnData::HivePartitionedColumnData(const HivePartitionedColumn
|
|
|
150
150
|
void HivePartitionedColumnData::ComputePartitionIndices(PartitionedColumnDataAppendState &state, DataChunk &input) {
|
|
151
151
|
Vector hashes(LogicalType::HASH, input.size());
|
|
152
152
|
input.Hash(group_by_columns, hashes);
|
|
153
|
+
hashes.Flatten(input.size());
|
|
153
154
|
|
|
154
155
|
for (idx_t i = 0; i < input.size(); i++) {
|
|
155
156
|
HivePartitionKey key;
|
|
@@ -833,8 +833,8 @@ static bool HasGlob(const string &str) {
|
|
|
833
833
|
return false;
|
|
834
834
|
}
|
|
835
835
|
|
|
836
|
-
static void
|
|
837
|
-
|
|
836
|
+
static void GlobFilesInternal(FileSystem &fs, const string &path, const string &glob, bool match_directory,
|
|
837
|
+
vector<string> &result, bool join_path) {
|
|
838
838
|
fs.ListFiles(path, [&](const string &fname, bool is_directory) {
|
|
839
839
|
if (is_directory != match_directory) {
|
|
840
840
|
return;
|
|
@@ -951,12 +951,12 @@ vector<string> LocalFileSystem::Glob(const string &path, FileOpener *opener) {
|
|
|
951
951
|
} else {
|
|
952
952
|
if (previous_directories.empty()) {
|
|
953
953
|
// no previous directories: list in the current path
|
|
954
|
-
|
|
954
|
+
GlobFilesInternal(*this, ".", splits[i], !is_last_chunk, result, false);
|
|
955
955
|
} else {
|
|
956
956
|
// previous directories
|
|
957
957
|
// we iterate over each of the previous directories, and apply the glob of the current directory
|
|
958
958
|
for (auto &prev_directory : previous_directories) {
|
|
959
|
-
|
|
959
|
+
GlobFilesInternal(*this, prev_directory, splits[i], !is_last_chunk, result, true);
|
|
960
960
|
}
|
|
961
961
|
}
|
|
962
962
|
}
|
|
@@ -1554,16 +1554,22 @@ dtime_t Cast::Operation(string_t input) {
|
|
|
1554
1554
|
//===--------------------------------------------------------------------===//
|
|
1555
1555
|
template <>
|
|
1556
1556
|
bool TryCastErrorMessage::Operation(string_t input, timestamp_t &result, string *error_message, bool strict) {
|
|
1557
|
-
|
|
1557
|
+
auto cast_result = Timestamp::TryConvertTimestamp(input.GetDataUnsafe(), input.GetSize(), result);
|
|
1558
|
+
if (cast_result == TimestampCastResult::SUCCESS) {
|
|
1559
|
+
return true;
|
|
1560
|
+
}
|
|
1561
|
+
if (cast_result == TimestampCastResult::ERROR_INCORRECT_FORMAT) {
|
|
1558
1562
|
HandleCastError::AssignError(Timestamp::ConversionError(input), error_message);
|
|
1559
|
-
|
|
1563
|
+
} else {
|
|
1564
|
+
HandleCastError::AssignError(Timestamp::UnsupportedTimezoneError(input), error_message);
|
|
1560
1565
|
}
|
|
1561
|
-
return
|
|
1566
|
+
return false;
|
|
1562
1567
|
}
|
|
1563
1568
|
|
|
1564
1569
|
template <>
|
|
1565
1570
|
bool TryCast::Operation(string_t input, timestamp_t &result, bool strict) {
|
|
1566
|
-
return Timestamp::TryConvertTimestamp(input.GetDataUnsafe(), input.GetSize(), result)
|
|
1571
|
+
return Timestamp::TryConvertTimestamp(input.GetDataUnsafe(), input.GetSize(), result) ==
|
|
1572
|
+
TimestampCastResult::SUCCESS;
|
|
1567
1573
|
}
|
|
1568
1574
|
|
|
1569
1575
|
template <>
|
|
@@ -249,7 +249,7 @@ private:
|
|
|
249
249
|
};
|
|
250
250
|
|
|
251
251
|
// adapted from https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++
|
|
252
|
-
idx_t StringUtil::LevenshteinDistance(const string &s1_p, const string &s2_p) {
|
|
252
|
+
idx_t StringUtil::LevenshteinDistance(const string &s1_p, const string &s2_p, idx_t not_equal_penalty) {
|
|
253
253
|
auto s1 = StringUtil::Lower(s1_p);
|
|
254
254
|
auto s2 = StringUtil::Lower(s2_p);
|
|
255
255
|
idx_t len1 = s1.size();
|
|
@@ -273,7 +273,7 @@ idx_t StringUtil::LevenshteinDistance(const string &s1_p, const string &s2_p) {
|
|
|
273
273
|
// d[i][j] = std::min({ d[i - 1][j] + 1,
|
|
274
274
|
// d[i][j - 1] + 1,
|
|
275
275
|
// d[i - 1][j - 1] + (s1[i - 1] == s2[j - 1] ? 0 : 1) });
|
|
276
|
-
int equal = s1[i - 1] == s2[j - 1] ? 0 :
|
|
276
|
+
int equal = s1[i - 1] == s2[j - 1] ? 0 : not_equal_penalty;
|
|
277
277
|
idx_t adjacent_score1 = array.Score(i - 1, j) + 1;
|
|
278
278
|
idx_t adjacent_score2 = array.Score(i, j - 1) + 1;
|
|
279
279
|
idx_t adjacent_score3 = array.Score(i - 1, j - 1) + equal;
|
|
@@ -285,15 +285,19 @@ idx_t StringUtil::LevenshteinDistance(const string &s1_p, const string &s2_p) {
|
|
|
285
285
|
return array.Score(len1, len2);
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
idx_t StringUtil::SimilarityScore(const string &s1, const string &s2) {
|
|
289
|
+
return LevenshteinDistance(s1, s2, 3);
|
|
290
|
+
}
|
|
291
|
+
|
|
288
292
|
vector<string> StringUtil::TopNLevenshtein(const vector<string> &strings, const string &target, idx_t n,
|
|
289
293
|
idx_t threshold) {
|
|
290
294
|
vector<pair<string, idx_t>> scores;
|
|
291
295
|
scores.reserve(strings.size());
|
|
292
296
|
for (auto &str : strings) {
|
|
293
297
|
if (target.size() < str.size()) {
|
|
294
|
-
scores.emplace_back(str,
|
|
298
|
+
scores.emplace_back(str, SimilarityScore(str.substr(0, target.size()), target));
|
|
295
299
|
} else {
|
|
296
|
-
scores.emplace_back(str,
|
|
300
|
+
scores.emplace_back(str, SimilarityScore(str, target));
|
|
297
301
|
}
|
|
298
302
|
}
|
|
299
303
|
return TopNStrings(scores, n, threshold);
|
|
@@ -137,6 +137,7 @@ void PartitionedColumnData::FlushAppendState(PartitionedColumnDataAppendState &s
|
|
|
137
137
|
auto &partition_buffer = *state.partition_buffers[i];
|
|
138
138
|
if (partition_buffer.size() > 0) {
|
|
139
139
|
partitions[i]->Append(partition_buffer);
|
|
140
|
+
partition_buffer.Reset();
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
}
|
|
@@ -115,7 +115,7 @@ bool Time::TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &resul
|
|
|
115
115
|
if (!strict) {
|
|
116
116
|
// last chance, check if we can parse as timestamp
|
|
117
117
|
timestamp_t timestamp;
|
|
118
|
-
if (Timestamp::TryConvertTimestamp(buf, len, timestamp)) {
|
|
118
|
+
if (Timestamp::TryConvertTimestamp(buf, len, timestamp) == TimestampCastResult::SUCCESS) {
|
|
119
119
|
if (!Timestamp::IsFinite(timestamp)) {
|
|
120
120
|
return false;
|
|
121
121
|
}
|
|
@@ -88,11 +88,27 @@ bool Timestamp::TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &r
|
|
|
88
88
|
return true;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
TimestampCastResult Timestamp::TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result) {
|
|
92
92
|
string_t tz(nullptr, 0);
|
|
93
93
|
bool has_offset = false;
|
|
94
94
|
// We don't understand TZ without an extension, so fail if one was provided.
|
|
95
|
-
|
|
95
|
+
auto success = TryConvertTimestampTZ(str, len, result, has_offset, tz);
|
|
96
|
+
if (!success) {
|
|
97
|
+
return TimestampCastResult::ERROR_INCORRECT_FORMAT;
|
|
98
|
+
}
|
|
99
|
+
if (tz.GetSize() == 0) {
|
|
100
|
+
// no timezone provided - success!
|
|
101
|
+
return TimestampCastResult::SUCCESS;
|
|
102
|
+
}
|
|
103
|
+
if (tz.GetSize() == 3) {
|
|
104
|
+
// we can ONLY handle UTC without ICU being loaded
|
|
105
|
+
auto tz_ptr = tz.GetDataUnsafe();
|
|
106
|
+
if ((tz_ptr[0] == 'u' || tz_ptr[0] == 'U') && (tz_ptr[1] == 't' || tz_ptr[1] == 'T') &&
|
|
107
|
+
(tz_ptr[2] == 'c' || tz_ptr[2] == 'C')) {
|
|
108
|
+
return TimestampCastResult::SUCCESS;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return TimestampCastResult::ERROR_NON_UTC_TIMEZONE;
|
|
96
112
|
}
|
|
97
113
|
|
|
98
114
|
string Timestamp::ConversionError(const string &str) {
|
|
@@ -101,16 +117,31 @@ string Timestamp::ConversionError(const string &str) {
|
|
|
101
117
|
str);
|
|
102
118
|
}
|
|
103
119
|
|
|
120
|
+
string Timestamp::UnsupportedTimezoneError(const string &str) {
|
|
121
|
+
return StringUtil::Format("timestamp field value \"%s\" has a timestamp that is not UTC.\nUse the TIMESTAMPTZ type "
|
|
122
|
+
"with the ICU extension loaded to handle non-UTC timestamps.",
|
|
123
|
+
str);
|
|
124
|
+
}
|
|
125
|
+
|
|
104
126
|
string Timestamp::ConversionError(string_t str) {
|
|
105
127
|
return Timestamp::ConversionError(str.GetString());
|
|
106
128
|
}
|
|
107
129
|
|
|
130
|
+
string Timestamp::UnsupportedTimezoneError(string_t str) {
|
|
131
|
+
return Timestamp::UnsupportedTimezoneError(str.GetString());
|
|
132
|
+
}
|
|
133
|
+
|
|
108
134
|
timestamp_t Timestamp::FromCString(const char *str, idx_t len) {
|
|
109
135
|
timestamp_t result;
|
|
110
|
-
|
|
136
|
+
auto cast_result = Timestamp::TryConvertTimestamp(str, len, result);
|
|
137
|
+
if (cast_result == TimestampCastResult::SUCCESS) {
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
if (cast_result == TimestampCastResult::ERROR_NON_UTC_TIMEZONE) {
|
|
141
|
+
throw ConversionException(Timestamp::UnsupportedTimezoneError(string(str, len)));
|
|
142
|
+
} else {
|
|
111
143
|
throw ConversionException(Timestamp::ConversionError(string(str, len)));
|
|
112
144
|
}
|
|
113
|
-
return result;
|
|
114
145
|
}
|
|
115
146
|
|
|
116
147
|
bool Timestamp::TryParseUTCOffset(const char *str, idx_t &pos, idx_t len, int &hour_offset, int &minute_offset) {
|
|
@@ -424,7 +424,7 @@ string LogicalType::ToString() const {
|
|
|
424
424
|
auto &child_types = StructType::GetChildTypes(*this);
|
|
425
425
|
string ret = "STRUCT(";
|
|
426
426
|
for (size_t i = 0; i < child_types.size(); i++) {
|
|
427
|
-
ret += child_types[i].first + " " + child_types[i].second.ToString();
|
|
427
|
+
ret += KeywordHelper::WriteOptionallyQuoted(child_types[i].first) + " " + child_types[i].second.ToString();
|
|
428
428
|
if (i < child_types.size() - 1) {
|
|
429
429
|
ret += ", ";
|
|
430
430
|
}
|
|
@@ -504,11 +504,32 @@ LogicalType TransformStringToLogicalType(const string &str) {
|
|
|
504
504
|
return Parser::ParseColumnList("dummy " + str).GetColumn(LogicalIndex(0)).Type();
|
|
505
505
|
}
|
|
506
506
|
|
|
507
|
+
LogicalType GetUserTypeRecursive(const LogicalType &type, ClientContext &context) {
|
|
508
|
+
if (type.id() == LogicalTypeId::USER && type.HasAlias()) {
|
|
509
|
+
return Catalog::GetSystemCatalog(context).GetType(context, SYSTEM_CATALOG, DEFAULT_SCHEMA, type.GetAlias());
|
|
510
|
+
}
|
|
511
|
+
// Look for LogicalTypeId::USER in nested types
|
|
512
|
+
if (type.id() == LogicalTypeId::STRUCT) {
|
|
513
|
+
child_list_t<LogicalType> children;
|
|
514
|
+
children.reserve(StructType::GetChildCount(type));
|
|
515
|
+
for (auto &child : StructType::GetChildTypes(type)) {
|
|
516
|
+
children.emplace_back(child.first, GetUserTypeRecursive(child.second, context));
|
|
517
|
+
}
|
|
518
|
+
return LogicalType::STRUCT(std::move(children));
|
|
519
|
+
}
|
|
520
|
+
if (type.id() == LogicalTypeId::LIST) {
|
|
521
|
+
return LogicalType::LIST(GetUserTypeRecursive(ListType::GetChildType(type), context));
|
|
522
|
+
}
|
|
523
|
+
if (type.id() == LogicalTypeId::MAP) {
|
|
524
|
+
return LogicalType::MAP(GetUserTypeRecursive(MapType::KeyType(type), context),
|
|
525
|
+
GetUserTypeRecursive(MapType::ValueType(type), context));
|
|
526
|
+
}
|
|
527
|
+
// Not LogicalTypeId::USER or a nested type
|
|
528
|
+
return type;
|
|
529
|
+
}
|
|
530
|
+
|
|
507
531
|
LogicalType TransformStringToLogicalType(const string &str, ClientContext &context) {
|
|
508
|
-
|
|
509
|
-
return type.id() == LogicalTypeId::USER
|
|
510
|
-
? Catalog::GetSystemCatalog(context).GetType(context, SYSTEM_CATALOG, DEFAULT_SCHEMA, str)
|
|
511
|
-
: type;
|
|
532
|
+
return GetUserTypeRecursive(TransformStringToLogicalType(str), context);
|
|
512
533
|
}
|
|
513
534
|
|
|
514
535
|
bool LogicalType::IsIntegral() const {
|
|
@@ -888,18 +909,23 @@ void LogicalType::SetAlias(string alias) {
|
|
|
888
909
|
}
|
|
889
910
|
|
|
890
911
|
string LogicalType::GetAlias() const {
|
|
891
|
-
if (
|
|
892
|
-
return
|
|
893
|
-
}
|
|
912
|
+
if (id() == LogicalTypeId::USER) {
|
|
913
|
+
return UserType::GetTypeName(*this);
|
|
914
|
+
}
|
|
915
|
+
if (type_info_) {
|
|
894
916
|
return type_info_->alias;
|
|
895
917
|
}
|
|
918
|
+
return string();
|
|
896
919
|
}
|
|
897
920
|
|
|
898
921
|
bool LogicalType::HasAlias() const {
|
|
899
|
-
if (
|
|
900
|
-
return
|
|
922
|
+
if (id() == LogicalTypeId::USER) {
|
|
923
|
+
return !UserType::GetTypeName(*this).empty();
|
|
924
|
+
}
|
|
925
|
+
if (type_info_ && !type_info_->alias.empty()) {
|
|
926
|
+
return true;
|
|
901
927
|
}
|
|
902
|
-
return
|
|
928
|
+
return false;
|
|
903
929
|
}
|
|
904
930
|
|
|
905
931
|
void LogicalType::SetCatalog(LogicalType &type, TypeCatalogEntry *catalog_entry) {
|
|
@@ -65,9 +65,12 @@ void ColumnBindingResolver::VisitOperator(LogicalOperator &op) {
|
|
|
65
65
|
// ON CONFLICT DO UPDATE clause
|
|
66
66
|
auto &insert_op = (LogicalInsert &)op;
|
|
67
67
|
if (insert_op.action_type != OnConflictAction::THROW) {
|
|
68
|
+
// Get the bindings from the children
|
|
68
69
|
VisitOperatorChildren(op);
|
|
69
|
-
auto
|
|
70
|
-
|
|
70
|
+
auto column_count = insert_op.table->GetColumns().PhysicalColumnCount();
|
|
71
|
+
auto dummy_bindings = LogicalOperator::GenerateColumnBindings(insert_op.excluded_table_index, column_count);
|
|
72
|
+
// Now insert our dummy bindings at the start of the bindings,
|
|
73
|
+
// so the first 'column_count' indices of the chunk are reserved for our 'excluded' columns
|
|
71
74
|
bindings.insert(bindings.begin(), dummy_bindings.begin(), dummy_bindings.end());
|
|
72
75
|
if (insert_op.on_conflict_condition) {
|
|
73
76
|
VisitExpression(&insert_op.on_conflict_condition);
|