duckdb 0.7.1-dev11.0 → 0.7.1-dev137.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/package.json +1 -1
- package/src/duckdb/extension/json/buffered_json_reader.cpp +29 -5
- package/src/duckdb/extension/json/include/buffered_json_reader.hpp +5 -1
- package/src/duckdb/extension/json/include/json_scan.hpp +17 -2
- package/src/duckdb/extension/json/json_functions/json_transform.cpp +19 -0
- package/src/duckdb/extension/json/json_functions/read_json.cpp +30 -28
- package/src/duckdb/extension/json/json_functions.cpp +6 -0
- package/src/duckdb/extension/json/json_scan.cpp +111 -23
- package/src/duckdb/extension/parquet/parquet-extension.cpp +3 -2
- 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 +14 -0
- package/src/duckdb/src/common/operator/cast_operators.cpp +14 -8
- package/src/duckdb/src/common/printer.cpp +1 -1
- 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 +36 -10
- package/src/duckdb/src/execution/column_binding_resolver.cpp +5 -2
- package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +6 -11
- package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +7 -13
- package/src/duckdb/src/execution/operator/persistent/parallel_csv_reader.cpp +1 -1
- 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_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 +36 -9
- package/src/duckdb/src/function/table/read_csv.cpp +15 -4
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- 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 +2 -1
- 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/types/timestamp.hpp +5 -1
- 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/main/client_data.hpp +2 -2
- package/src/duckdb/src/include/duckdb/main/config.hpp +0 -3
- 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/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/tokens.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +1 -0
- package/src/duckdb/src/include/duckdb/planner/binder.hpp +1 -0
- 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/storage_extension.hpp +7 -0
- package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +2 -0
- package/src/duckdb/src/parser/statement/copy_statement.cpp +2 -13
- package/src/duckdb/src/parser/statement/detach_statement.cpp +15 -0
- package/src/duckdb/src/parser/statement/insert_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/binder/statement/bind_create.cpp +16 -14
- 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/tableref/bind_joinref.cpp +2 -1
- package/src/duckdb/src/planner/binder.cpp +2 -0
- package/src/duckdb/src/planner/expression_binder/lateral_binder.cpp +21 -5
- package/src/duckdb/src/planner/logical_operator.cpp +4 -0
- package/src/duckdb/src/planner/planner.cpp +1 -0
- package/src/duckdb/src/storage/storage_info.cpp +2 -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/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_src_execution_operator_schema.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/duckdb/src/include/duckdb/function/create_database_extension.hpp +0 -37
|
@@ -335,6 +335,20 @@ bool FileSystem::CanHandleFile(const string &fpath) {
|
|
|
335
335
|
throw NotImplementedException("%s: CanHandleFile is not implemented!", GetName());
|
|
336
336
|
}
|
|
337
337
|
|
|
338
|
+
IOException FileSystem::MissingFileException(const string &file_path, ClientContext &context) {
|
|
339
|
+
const string prefixes[] = {"http://", "https://", "s3://"};
|
|
340
|
+
for (auto &prefix : prefixes) {
|
|
341
|
+
if (StringUtil::StartsWith(file_path, prefix)) {
|
|
342
|
+
if (!context.db->LoadedExtensions().count("httpfs")) {
|
|
343
|
+
return MissingExtensionException("No files found that match the pattern \"%s\", because the httpfs "
|
|
344
|
+
"extension is not loaded. Try loading the extension: LOAD HTTPFS",
|
|
345
|
+
file_path);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return IOException("No files found that match the pattern \"%s\"", file_path);
|
|
350
|
+
}
|
|
351
|
+
|
|
338
352
|
void FileSystem::Seek(FileHandle &handle, idx_t location) {
|
|
339
353
|
throw NotImplementedException("%s: Seek is not implemented!", GetName());
|
|
340
354
|
}
|
|
@@ -946,13 +946,13 @@ static bool IntegerCastLoop(const char *buf, idx_t len, T &result, bool strict)
|
|
|
946
946
|
ExponentData exponent {0, false};
|
|
947
947
|
int negative = buf[pos] == '-';
|
|
948
948
|
if (negative) {
|
|
949
|
-
if (!IntegerCastLoop<ExponentData, true, false, IntegerCastOperation>(
|
|
950
|
-
|
|
949
|
+
if (!IntegerCastLoop<ExponentData, true, false, IntegerCastOperation, decimal_separator>(
|
|
950
|
+
buf + pos, len - pos, exponent, strict)) {
|
|
951
951
|
return false;
|
|
952
952
|
}
|
|
953
953
|
} else {
|
|
954
|
-
if (!IntegerCastLoop<ExponentData, false, false, IntegerCastOperation>(
|
|
955
|
-
|
|
954
|
+
if (!IntegerCastLoop<ExponentData, false, false, IntegerCastOperation, decimal_separator>(
|
|
955
|
+
buf + pos, len - pos, exponent, strict)) {
|
|
956
956
|
return false;
|
|
957
957
|
}
|
|
958
958
|
}
|
|
@@ -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 <>
|
|
@@ -65,7 +65,7 @@ idx_t Printer::TerminalWidth() {
|
|
|
65
65
|
int columns, rows;
|
|
66
66
|
|
|
67
67
|
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
|
|
68
|
-
rows = csbi.srWindow.
|
|
68
|
+
rows = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
|
69
69
|
return rows;
|
|
70
70
|
#else
|
|
71
71
|
struct winsize w;
|
|
@@ -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) {
|
|
@@ -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);
|
|
@@ -30,15 +30,10 @@ string BaseCSVReader::GetLineNumberStr(idx_t linenr, bool linenr_estimated) {
|
|
|
30
30
|
return to_string(linenr + 1) + estimated;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
BaseCSVReader::BaseCSVReader(
|
|
34
|
-
BufferedCSVReaderOptions options_p, const vector<LogicalType> &requested_types)
|
|
35
|
-
: fs(fs_p), allocator(allocator), opener(opener_p), options(std::move(options_p)) {
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
BaseCSVReader::BaseCSVReader(ClientContext &context, BufferedCSVReaderOptions options_p,
|
|
33
|
+
BaseCSVReader::BaseCSVReader(ClientContext &context_p, BufferedCSVReaderOptions options_p,
|
|
39
34
|
const vector<LogicalType> &requested_types)
|
|
40
|
-
:
|
|
41
|
-
|
|
35
|
+
: context(context_p), fs(FileSystem::GetFileSystem(context)), allocator(Allocator::Get(context)),
|
|
36
|
+
opener(FileSystem::GetFileOpener(context)), options(std::move(options_p)) {
|
|
42
37
|
}
|
|
43
38
|
|
|
44
39
|
BaseCSVReader::~BaseCSVReader() {
|
|
@@ -144,7 +139,7 @@ bool BaseCSVReader::TryCastValue(const Value &value, const LogicalType &sql_type
|
|
|
144
139
|
} else {
|
|
145
140
|
Value new_value;
|
|
146
141
|
string error_message;
|
|
147
|
-
return value.
|
|
142
|
+
return value.TryCastAs(context, sql_type, new_value, &error_message, true);
|
|
148
143
|
}
|
|
149
144
|
}
|
|
150
145
|
|
|
@@ -481,8 +476,8 @@ bool BaseCSVReader::Flush(DataChunk &insert_chunk, bool try_add_line) {
|
|
|
481
476
|
error_message, return_types[col_idx]);
|
|
482
477
|
} else {
|
|
483
478
|
// target type is not varchar: perform a cast
|
|
484
|
-
success = VectorOperations::
|
|
485
|
-
|
|
479
|
+
success = VectorOperations::TryCast(context, parse_chunk.data[col_idx], insert_chunk.data[insert_idx],
|
|
480
|
+
parse_chunk.size(), &error_message);
|
|
486
481
|
}
|
|
487
482
|
if (success) {
|
|
488
483
|
continue;
|
|
@@ -23,25 +23,16 @@
|
|
|
23
23
|
|
|
24
24
|
namespace duckdb {
|
|
25
25
|
|
|
26
|
-
BufferedCSVReader::BufferedCSVReader(FileSystem &fs_p, Allocator &allocator, FileOpener *opener_p,
|
|
27
|
-
BufferedCSVReaderOptions options_p, const vector<LogicalType> &requested_types)
|
|
28
|
-
: BaseCSVReader(fs_p, allocator, opener_p, std::move(options_p), requested_types), buffer_size(0), position(0),
|
|
29
|
-
start(0) {
|
|
30
|
-
file_handle = OpenCSV(options);
|
|
31
|
-
Initialize(requested_types);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
26
|
BufferedCSVReader::BufferedCSVReader(ClientContext &context, BufferedCSVReaderOptions options_p,
|
|
35
27
|
const vector<LogicalType> &requested_types)
|
|
36
|
-
:
|
|
37
|
-
|
|
28
|
+
: BaseCSVReader(context, std::move(options_p), requested_types), buffer_size(0), position(0), start(0) {
|
|
29
|
+
file_handle = OpenCSV(options);
|
|
30
|
+
Initialize(requested_types);
|
|
38
31
|
}
|
|
39
32
|
|
|
40
33
|
BufferedCSVReader::BufferedCSVReader(ClientContext &context, string filename, BufferedCSVReaderOptions options_p,
|
|
41
34
|
const vector<LogicalType> &requested_types)
|
|
42
|
-
: BaseCSVReader(
|
|
43
|
-
std::move(options_p), requested_types),
|
|
44
|
-
buffer_size(0), position(0), start(0) {
|
|
35
|
+
: BaseCSVReader(context, std::move(options_p), requested_types), buffer_size(0), position(0), start(0) {
|
|
45
36
|
options.file_path = std::move(filename);
|
|
46
37
|
file_handle = OpenCSV(options);
|
|
47
38
|
Initialize(requested_types);
|
|
@@ -730,6 +721,9 @@ void BufferedCSVReader::DetectHeader(const vector<vector<LogicalType>> &best_sql
|
|
|
730
721
|
names.push_back(column_name);
|
|
731
722
|
}
|
|
732
723
|
}
|
|
724
|
+
for (idx_t i = 0; i < MinValue<idx_t>(names.size(), options.name_list.size()); i++) {
|
|
725
|
+
names[i] = options.name_list[i];
|
|
726
|
+
}
|
|
733
727
|
}
|
|
734
728
|
|
|
735
729
|
vector<LogicalType> BufferedCSVReader::RefineTypeDetection(const vector<LogicalType> &type_candidates,
|
|
@@ -60,7 +60,7 @@ bool ParallelCSVReader::SetPosition(DataChunk &insert_chunk) {
|
|
|
60
60
|
verification_positions.end_of_last_line = position_buffer;
|
|
61
61
|
// First buffer doesn't need any setting
|
|
62
62
|
// Unless we have a header
|
|
63
|
-
if (options.header
|
|
63
|
+
if (options.header) {
|
|
64
64
|
for (; position_buffer < end_buffer; position_buffer++) {
|
|
65
65
|
if (StringUtil::CharacterIsNewline((*buffer)[position_buffer])) {
|
|
66
66
|
bool carrier_return = (*buffer)[position_buffer] == '\r';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#include "duckdb/execution/operator/schema/physical_detach.hpp"
|
|
2
|
+
#include "duckdb/parser/parsed_data/detach_info.hpp"
|
|
3
|
+
#include "duckdb/catalog/catalog.hpp"
|
|
4
|
+
#include "duckdb/main/database_manager.hpp"
|
|
5
|
+
#include "duckdb/main/attached_database.hpp"
|
|
6
|
+
#include "duckdb/main/database.hpp"
|
|
7
|
+
#include "duckdb/storage/storage_extension.hpp"
|
|
8
|
+
|
|
9
|
+
namespace duckdb {
|
|
10
|
+
|
|
11
|
+
//===--------------------------------------------------------------------===//
|
|
12
|
+
// Source
|
|
13
|
+
//===--------------------------------------------------------------------===//
|
|
14
|
+
class DetachSourceState : public GlobalSourceState {
|
|
15
|
+
public:
|
|
16
|
+
DetachSourceState() : finished(false) {
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
bool finished;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
unique_ptr<GlobalSourceState> PhysicalDetach::GetGlobalSourceState(ClientContext &context) const {
|
|
23
|
+
return make_unique<DetachSourceState>();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void PhysicalDetach::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate,
|
|
27
|
+
LocalSourceState &lstate) const {
|
|
28
|
+
auto &state = (DetachSourceState &)gstate;
|
|
29
|
+
if (state.finished) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
auto &db_manager = DatabaseManager::Get(context.client);
|
|
33
|
+
db_manager.DetachDatabase(context.client, info->name, info->if_exists);
|
|
34
|
+
state.finished = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
} // namespace duckdb
|
|
@@ -38,11 +38,6 @@ void PhysicalDrop::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSo
|
|
|
38
38
|
}
|
|
39
39
|
break;
|
|
40
40
|
}
|
|
41
|
-
case CatalogType::DATABASE_ENTRY: {
|
|
42
|
-
auto &db_manager = DatabaseManager::Get(context.client);
|
|
43
|
-
db_manager.DetachDatabase(context.client, info->name, info->if_exists);
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
41
|
case CatalogType::SCHEMA_ENTRY: {
|
|
47
42
|
auto &catalog = Catalog::GetCatalog(context.client, info->catalog);
|
|
48
43
|
catalog.DropEntry(context.client, info.get());
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include "duckdb/execution/operator/schema/physical_create_schema.hpp"
|
|
7
7
|
#include "duckdb/execution/operator/schema/physical_create_sequence.hpp"
|
|
8
8
|
#include "duckdb/execution/operator/schema/physical_create_view.hpp"
|
|
9
|
+
#include "duckdb/execution/operator/schema/physical_detach.hpp"
|
|
9
10
|
#include "duckdb/execution/operator/schema/physical_drop.hpp"
|
|
10
11
|
#include "duckdb/execution/physical_plan_generator.hpp"
|
|
11
12
|
#include "duckdb/planner/logical_operator.hpp"
|
|
@@ -39,6 +40,9 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalSimple &op
|
|
|
39
40
|
case LogicalOperatorType::LOGICAL_ATTACH:
|
|
40
41
|
return make_unique<PhysicalAttach>(unique_ptr_cast<ParseInfo, AttachInfo>(std::move(op.info)),
|
|
41
42
|
op.estimated_cardinality);
|
|
43
|
+
case LogicalOperatorType::LOGICAL_DETACH:
|
|
44
|
+
return make_unique<PhysicalDetach>(unique_ptr_cast<ParseInfo, DetachInfo>(std::move(op.info)),
|
|
45
|
+
op.estimated_cardinality);
|
|
42
46
|
default:
|
|
43
47
|
throw NotImplementedException("Unimplemented type for logical simple operator");
|
|
44
48
|
}
|
|
@@ -184,6 +184,7 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalOperator &
|
|
|
184
184
|
case LogicalOperatorType::LOGICAL_VACUUM:
|
|
185
185
|
case LogicalOperatorType::LOGICAL_LOAD:
|
|
186
186
|
case LogicalOperatorType::LOGICAL_ATTACH:
|
|
187
|
+
case LogicalOperatorType::LOGICAL_DETACH:
|
|
187
188
|
plan = CreatePlan((LogicalSimple &)op);
|
|
188
189
|
break;
|
|
189
190
|
case LogicalOperatorType::LOGICAL_RECURSIVE_CTE:
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
#include "duckdb/
|
|
2
|
-
#include "duckdb/common/string_util.hpp"
|
|
1
|
+
#include "duckdb/common/constants.hpp"
|
|
3
2
|
#include "duckdb/common/file_system.hpp"
|
|
4
|
-
#include "duckdb/
|
|
5
|
-
#include "duckdb/
|
|
6
|
-
#include "duckdb/parser/parser.hpp"
|
|
3
|
+
#include "duckdb/common/string_util.hpp"
|
|
4
|
+
#include "duckdb/function/pragma/pragma_functions.hpp"
|
|
7
5
|
#include "duckdb/main/config.hpp"
|
|
6
|
+
#include "duckdb/parser/parser.hpp"
|
|
7
|
+
#include "duckdb/parser/qualified_name.hpp"
|
|
8
|
+
#include "duckdb/parser/statement/copy_statement.hpp"
|
|
9
|
+
#include "duckdb/parser/statement/export_statement.hpp"
|
|
8
10
|
|
|
9
11
|
namespace duckdb {
|
|
10
12
|
|
|
@@ -58,10 +60,35 @@ string PragmaFunctionsQuery(ClientContext &context, const FunctionParameters &pa
|
|
|
58
60
|
|
|
59
61
|
string PragmaShow(ClientContext &context, const FunctionParameters ¶meters) {
|
|
60
62
|
// PRAGMA table_info but with some aliases
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
auto table = QualifiedName::Parse(parameters.values[0].ToString());
|
|
64
|
+
|
|
65
|
+
// clang-format off
|
|
66
|
+
string sql = R"(
|
|
67
|
+
SELECT
|
|
68
|
+
name AS "column_name",
|
|
69
|
+
type as "column_type",
|
|
70
|
+
CASE WHEN "notnull" THEN 'NO' ELSE 'YES' END AS "null",
|
|
71
|
+
(SELECT
|
|
72
|
+
MIN(CASE
|
|
73
|
+
WHEN constraint_type='PRIMARY KEY' THEN 'PRI'
|
|
74
|
+
WHEN constraint_type='UNIQUE' THEN 'UNI'
|
|
75
|
+
ELSE NULL END)
|
|
76
|
+
FROM duckdb_constraints() c
|
|
77
|
+
WHERE c.table_oid=cols.table_oid
|
|
78
|
+
AND list_contains(constraint_column_names, cols.column_name)) AS "key",
|
|
79
|
+
dflt_value AS "default",
|
|
80
|
+
NULL AS "extra"
|
|
81
|
+
FROM pragma_table_info('%func_param_table%')
|
|
82
|
+
LEFT JOIN duckdb_columns cols
|
|
83
|
+
ON cols.column_name = pragma_table_info.name
|
|
84
|
+
AND cols.table_name='%table_name%'
|
|
85
|
+
AND cols.schema_name='%table_schema%';)";
|
|
86
|
+
// clang-format on
|
|
87
|
+
|
|
88
|
+
sql = StringUtil::Replace(sql, "%func_param_table%", parameters.values[0].ToString());
|
|
89
|
+
sql = StringUtil::Replace(sql, "%table_name%", table.name);
|
|
90
|
+
sql = StringUtil::Replace(sql, "%table_schema%", table.schema.empty() ? DEFAULT_SCHEMA : table.schema);
|
|
91
|
+
return sql;
|
|
65
92
|
}
|
|
66
93
|
|
|
67
94
|
string PragmaVersion(ClientContext &context, const FunctionParameters ¶meters) {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "duckdb/parser/expression/function_expression.hpp"
|
|
11
11
|
#include "duckdb/parser/tableref/table_function_ref.hpp"
|
|
12
12
|
#include "duckdb/planner/operator/logical_get.hpp"
|
|
13
|
+
#include "duckdb/main/extension_helper.hpp"
|
|
13
14
|
|
|
14
15
|
#include <limits>
|
|
15
16
|
|
|
@@ -29,7 +30,7 @@ void ReadCSVData::InitializeFiles(ClientContext &context, const vector<string> &
|
|
|
29
30
|
for (auto &file_pattern : patterns) {
|
|
30
31
|
auto found_files = fs.Glob(file_pattern, context);
|
|
31
32
|
if (found_files.empty()) {
|
|
32
|
-
throw
|
|
33
|
+
throw FileSystem::MissingFileException(file_pattern, context);
|
|
33
34
|
}
|
|
34
35
|
files.insert(files.end(), found_files.begin(), found_files.end());
|
|
35
36
|
}
|
|
@@ -98,6 +99,17 @@ static unique_ptr<FunctionData> ReadCSVBind(ClientContext &context, TableFunctio
|
|
|
98
99
|
if (names.empty()) {
|
|
99
100
|
throw BinderException("read_csv requires at least a single column as input!");
|
|
100
101
|
}
|
|
102
|
+
} else if (loption == "column_names" || loption == "names") {
|
|
103
|
+
if (!options.name_list.empty()) {
|
|
104
|
+
throw BinderException("read_csv_auto column_names/names can only be supplied once");
|
|
105
|
+
}
|
|
106
|
+
if (kv.second.IsNull()) {
|
|
107
|
+
throw BinderException("read_csv_auto %s cannot be NULL", kv.first);
|
|
108
|
+
}
|
|
109
|
+
auto &children = ListValue::GetChildren(kv.second);
|
|
110
|
+
for (auto &child : children) {
|
|
111
|
+
options.name_list.push_back(StringValue::Get(child));
|
|
112
|
+
}
|
|
101
113
|
} else if (loption == "column_types" || loption == "types" || loption == "dtypes") {
|
|
102
114
|
auto &child_type = kv.second.type();
|
|
103
115
|
if (child_type.id() != LogicalTypeId::STRUCT && child_type.id() != LogicalTypeId::LIST) {
|
|
@@ -251,9 +263,6 @@ public:
|
|
|
251
263
|
: file_handle(std::move(file_handle_p)), system_threads(system_threads_p), buffer_size(buffer_size_p),
|
|
252
264
|
force_parallelism(force_parallelism_p) {
|
|
253
265
|
current_file_path = files_path_p[0];
|
|
254
|
-
for (idx_t i = 0; i < rows_to_skip; i++) {
|
|
255
|
-
file_handle->ReadLine();
|
|
256
|
-
}
|
|
257
266
|
estimated_linenr = rows_to_skip;
|
|
258
267
|
file_size = file_handle->FileSize();
|
|
259
268
|
first_file_size = file_size;
|
|
@@ -963,6 +972,8 @@ TableFunction ReadCSVTableFunction::GetAutoFunction(bool list_parameter) {
|
|
|
963
972
|
read_csv_auto.named_parameters["column_types"] = LogicalType::ANY;
|
|
964
973
|
read_csv_auto.named_parameters["dtypes"] = LogicalType::ANY;
|
|
965
974
|
read_csv_auto.named_parameters["types"] = LogicalType::ANY;
|
|
975
|
+
read_csv_auto.named_parameters["names"] = LogicalType::LIST(LogicalType::VARCHAR);
|
|
976
|
+
read_csv_auto.named_parameters["column_names"] = LogicalType::LIST(LogicalType::VARCHAR);
|
|
966
977
|
return read_csv_auto;
|
|
967
978
|
}
|
|
968
979
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
|
2
|
-
#define DUCKDB_VERSION "0.7.1-
|
|
2
|
+
#define DUCKDB_VERSION "0.7.1-dev137"
|
|
3
3
|
#endif
|
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
|
5
|
+
#define DUCKDB_SOURCE_ID "eb65c593fe"
|
|
6
6
|
#endif
|
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
|
8
8
|
#include "duckdb/main/database.hpp"
|
|
@@ -262,6 +262,16 @@ public:
|
|
|
262
262
|
}
|
|
263
263
|
};
|
|
264
264
|
|
|
265
|
+
class MissingExtensionException : public IOException {
|
|
266
|
+
public:
|
|
267
|
+
DUCKDB_API explicit MissingExtensionException(const string &msg);
|
|
268
|
+
|
|
269
|
+
template <typename... Args>
|
|
270
|
+
explicit MissingExtensionException(const string &msg, Args... params)
|
|
271
|
+
: IOException(ConstructMessage(msg, params...)) {
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
265
275
|
class SerializationException : public Exception {
|
|
266
276
|
public:
|
|
267
277
|
DUCKDB_API explicit SerializationException(const string &msg);
|
|
@@ -201,6 +201,7 @@ public:
|
|
|
201
201
|
|
|
202
202
|
//! Whether or not a sub-system can handle a specific file path
|
|
203
203
|
DUCKDB_API virtual bool CanHandleFile(const string &fpath);
|
|
204
|
+
DUCKDB_API static IOException MissingFileException(const string &file_path, ClientContext &context);
|
|
204
205
|
|
|
205
206
|
//! Set the file pointer of a file handle to a specified location. Reads and writes will happen from this location
|
|
206
207
|
DUCKDB_API virtual void Seek(FileHandle &handle, idx_t location);
|
|
@@ -93,6 +93,8 @@ struct timestamp_ns_t : public timestamp_t {}; // NOLINT
|
|
|
93
93
|
struct timestamp_ms_t : public timestamp_t {}; // NOLINT
|
|
94
94
|
struct timestamp_sec_t : public timestamp_t {}; // NOLINT
|
|
95
95
|
|
|
96
|
+
enum class TimestampCastResult : uint8_t { SUCCESS, ERROR_INCORRECT_FORMAT, ERROR_NON_UTC_TIMEZONE };
|
|
97
|
+
|
|
96
98
|
//! The Timestamp class is a static class that holds helper functions for the Timestamp
|
|
97
99
|
//! type.
|
|
98
100
|
class Timestamp {
|
|
@@ -110,7 +112,7 @@ public:
|
|
|
110
112
|
//! If the tz is not empty, the result is still an instant, but the parts can be extracted and applied to the TZ
|
|
111
113
|
DUCKDB_API static bool TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &result, bool &has_offset,
|
|
112
114
|
string_t &tz);
|
|
113
|
-
DUCKDB_API static
|
|
115
|
+
DUCKDB_API static TimestampCastResult TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result);
|
|
114
116
|
DUCKDB_API static timestamp_t FromCString(const char *str, idx_t len);
|
|
115
117
|
//! Convert a date object to a string in the format "YYYY-MM-DD hh:mm:ss"
|
|
116
118
|
DUCKDB_API static string ToString(timestamp_t timestamp);
|
|
@@ -161,6 +163,8 @@ public:
|
|
|
161
163
|
|
|
162
164
|
DUCKDB_API static string ConversionError(const string &str);
|
|
163
165
|
DUCKDB_API static string ConversionError(string_t str);
|
|
166
|
+
DUCKDB_API static string UnsupportedTimezoneError(const string &str);
|
|
167
|
+
DUCKDB_API static string UnsupportedTimezoneError(string_t str);
|
|
164
168
|
};
|
|
165
169
|
|
|
166
170
|
} // namespace duckdb
|
|
@@ -35,11 +35,9 @@ class BaseCSVReader {
|
|
|
35
35
|
public:
|
|
36
36
|
BaseCSVReader(ClientContext &context, BufferedCSVReaderOptions options,
|
|
37
37
|
const vector<LogicalType> &requested_types = vector<LogicalType>());
|
|
38
|
-
|
|
39
|
-
BaseCSVReader(FileSystem &fs, Allocator &allocator, FileOpener *opener, BufferedCSVReaderOptions options,
|
|
40
|
-
const vector<LogicalType> &requested_types = vector<LogicalType>());
|
|
41
38
|
~BaseCSVReader();
|
|
42
39
|
|
|
40
|
+
ClientContext &context;
|
|
43
41
|
FileSystem &fs;
|
|
44
42
|
Allocator &allocator;
|
|
45
43
|
FileOpener *opener;
|
|
@@ -55,8 +55,6 @@ class BufferedCSVReader : public BaseCSVReader {
|
|
|
55
55
|
public:
|
|
56
56
|
BufferedCSVReader(ClientContext &context, BufferedCSVReaderOptions options,
|
|
57
57
|
const vector<LogicalType> &requested_types = vector<LogicalType>());
|
|
58
|
-
BufferedCSVReader(FileSystem &fs, Allocator &allocator, FileOpener *opener, BufferedCSVReaderOptions options,
|
|
59
|
-
const vector<LogicalType> &requested_types = vector<LogicalType>());
|
|
60
58
|
BufferedCSVReader(ClientContext &context, string filename, BufferedCSVReaderOptions options,
|
|
61
59
|
const vector<LogicalType> &requested_types = vector<LogicalType>());
|
|
62
60
|
~BufferedCSVReader();
|
|
@@ -75,6 +75,8 @@ struct BufferedCSVReaderOptions {
|
|
|
75
75
|
case_insensitive_map_t<idx_t> sql_types_per_column;
|
|
76
76
|
//! User-defined SQL type list
|
|
77
77
|
vector<LogicalType> sql_type_list;
|
|
78
|
+
//! User-defined name list
|
|
79
|
+
vector<string> name_list;
|
|
78
80
|
//===--------------------------------------------------------------------===//
|
|
79
81
|
// ReadCSVOptions
|
|
80
82
|
//===--------------------------------------------------------------------===//
|