duckdb 0.7.2-dev2820.0 → 0.7.2-dev2867.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/icu/icu-datepart.cpp +51 -1
- package/src/duckdb/extension/parquet/parquet-extension.cpp +5 -4
- package/src/duckdb/src/common/local_file_system.cpp +1 -3
- package/src/duckdb/src/common/multi_file_reader.cpp +11 -8
- package/src/duckdb/src/execution/operator/schema/physical_create_type.cpp +11 -2
- package/src/duckdb/src/function/table/read_csv.cpp +7 -4
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/multi_file_reader.hpp +5 -4
- package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_create_type.hpp +4 -0
- package/src/duckdb/src/include/duckdb/main/database.hpp +1 -0
- package/src/duckdb/src/include/duckdb/main/database_manager.hpp +3 -0
- package/src/duckdb/src/include/duckdb/main/extension_helper.hpp +0 -2
- package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +5 -1
- package/src/duckdb/src/main/attached_database.cpp +5 -3
- package/src/duckdb/src/main/database.cpp +34 -37
- package/src/duckdb/src/main/extension/extension_load.cpp +13 -34
- package/src/duckdb/src/parser/transform/statement/transform_create_function.cpp +1 -4
- package/src/duckdb/src/parser/transform/statement/transform_create_view.cpp +2 -4
- package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +43 -24
- package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +3 -0
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +17 -28
- package/src/duckdb/third_party/fmt/format.cc +0 -5
- package/src/duckdb/third_party/fmt/include/fmt/core.h +10 -12
- package/src/duckdb/third_party/fmt/include/fmt/format-inl.h +2 -33
- package/src/duckdb/third_party/fmt/include/fmt/format.h +61 -24
- package/src/duckdb/third_party/fmt/include/fmt/printf.h +15 -1
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +1 -0
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +10735 -10674
@@ -18,33 +18,45 @@
|
|
18
18
|
|
19
19
|
namespace duckdb {
|
20
20
|
|
21
|
-
void Transformer::AddPivotEntry(string enum_name, unique_ptr<SelectNode> base, unique_ptr<ParsedExpression> column
|
21
|
+
void Transformer::AddPivotEntry(string enum_name, unique_ptr<SelectNode> base, unique_ptr<ParsedExpression> column,
|
22
|
+
unique_ptr<QueryNode> subquery) {
|
22
23
|
if (parent) {
|
23
|
-
parent->AddPivotEntry(std::move(enum_name), std::move(base), std::move(column));
|
24
|
+
parent->AddPivotEntry(std::move(enum_name), std::move(base), std::move(column), std::move(subquery));
|
24
25
|
return;
|
25
26
|
}
|
26
27
|
auto result = make_uniq<CreatePivotEntry>();
|
27
28
|
result->enum_name = std::move(enum_name);
|
28
29
|
result->base = std::move(base);
|
29
30
|
result->column = std::move(column);
|
31
|
+
result->subquery = std::move(subquery);
|
30
32
|
|
31
33
|
pivot_entries.push_back(std::move(result));
|
32
34
|
}
|
33
35
|
|
34
36
|
bool Transformer::HasPivotEntries() {
|
35
|
-
|
36
|
-
return parent->HasPivotEntries();
|
37
|
-
}
|
38
|
-
return !pivot_entries.empty();
|
37
|
+
return !GetPivotEntries().empty();
|
39
38
|
}
|
40
39
|
|
41
40
|
idx_t Transformer::PivotEntryCount() {
|
41
|
+
return GetPivotEntries().size();
|
42
|
+
}
|
43
|
+
|
44
|
+
vector<unique_ptr<Transformer::CreatePivotEntry>> &Transformer::GetPivotEntries() {
|
42
45
|
if (parent) {
|
43
|
-
return parent->
|
46
|
+
return parent->GetPivotEntries();
|
44
47
|
}
|
45
|
-
return pivot_entries
|
48
|
+
return pivot_entries;
|
46
49
|
}
|
47
50
|
|
51
|
+
void Transformer::PivotEntryCheck(const string &type) {
|
52
|
+
auto &entries = GetPivotEntries();
|
53
|
+
if (!entries.empty()) {
|
54
|
+
throw ParserException(
|
55
|
+
"PIVOT statements with pivot elements extracted from the data cannot be used in %ss.\nIn order to use "
|
56
|
+
"PIVOT in a %s the PIVOT values must be manually specified, e.g.:\nPIVOT ... ON %s IN (val1, val2, ...)",
|
57
|
+
type, type, entries[0]->column->ToString());
|
58
|
+
}
|
59
|
+
}
|
48
60
|
unique_ptr<SQLStatement> Transformer::GenerateCreateEnumStmt(unique_ptr<CreatePivotEntry> entry) {
|
49
61
|
auto result = make_uniq<CreateStatement>();
|
50
62
|
auto info = make_uniq<CreateTypeInfo>();
|
@@ -57,23 +69,30 @@ unique_ptr<SQLStatement> Transformer::GenerateCreateEnumStmt(unique_ptr<CreatePi
|
|
57
69
|
info->on_conflict = OnCreateConflict::REPLACE_ON_CONFLICT;
|
58
70
|
|
59
71
|
// generate the query that will result in the enum creation
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
unique_ptr<QueryNode> subselect;
|
73
|
+
if (!entry->subquery) {
|
74
|
+
auto select_node = std::move(entry->base);
|
75
|
+
auto columnref = entry->column->Copy();
|
76
|
+
auto cast = make_uniq<CastExpression>(LogicalType::VARCHAR, std::move(columnref));
|
77
|
+
select_node->select_list.push_back(std::move(cast));
|
78
|
+
|
79
|
+
auto is_not_null =
|
80
|
+
make_uniq<OperatorExpression>(ExpressionType::OPERATOR_IS_NOT_NULL, std::move(entry->column));
|
81
|
+
select_node->where_clause = std::move(is_not_null);
|
82
|
+
|
83
|
+
// order by the column
|
84
|
+
select_node->modifiers.push_back(make_uniq<DistinctModifier>());
|
85
|
+
auto modifier = make_uniq<OrderModifier>();
|
86
|
+
modifier->orders.emplace_back(OrderType::ASCENDING, OrderByNullType::ORDER_DEFAULT,
|
87
|
+
make_uniq<ConstantExpression>(Value::INTEGER(1)));
|
88
|
+
select_node->modifiers.push_back(std::move(modifier));
|
89
|
+
subselect = std::move(select_node);
|
90
|
+
} else {
|
91
|
+
subselect = std::move(entry->subquery);
|
92
|
+
}
|
74
93
|
|
75
94
|
auto select = make_uniq<SelectStatement>();
|
76
|
-
select->node = std::move(
|
95
|
+
select->node = std::move(subselect);
|
77
96
|
info->query = std::move(select);
|
78
97
|
info->type = LogicalType::INVALID;
|
79
98
|
|
@@ -150,7 +169,7 @@ unique_ptr<QueryNode> Transformer::TransformPivotStatement(duckdb_libpgquery::PG
|
|
150
169
|
auto new_select = make_uniq<SelectNode>();
|
151
170
|
ExtractCTEsRecursive(new_select->cte_map);
|
152
171
|
new_select->from_table = source->Copy();
|
153
|
-
AddPivotEntry(enum_name, std::move(new_select), col.pivot_expressions[0]->Copy());
|
172
|
+
AddPivotEntry(enum_name, std::move(new_select), col.pivot_expressions[0]->Copy(), std::move(col.subquery));
|
154
173
|
col.pivot_enum = enum_name;
|
155
174
|
}
|
156
175
|
|
@@ -59,6 +59,9 @@ PivotColumn Transformer::TransformPivotColumn(duckdb_libpgquery::PGPivot *pivot)
|
|
59
59
|
col.entries.push_back(std::move(entry));
|
60
60
|
}
|
61
61
|
}
|
62
|
+
if (pivot->subquery) {
|
63
|
+
col.subquery = TransformSelectNode(reinterpret_cast<duckdb_libpgquery::PGSelectStmt *>(pivot->subquery));
|
64
|
+
}
|
62
65
|
if (pivot->pivot_enum) {
|
63
66
|
col.pivot_enum = pivot->pivot_enum;
|
64
67
|
}
|
@@ -8,6 +8,8 @@
|
|
8
8
|
#include "duckdb/parser/expression/constant_expression.hpp"
|
9
9
|
#include "duckdb/parser/expression/function_expression.hpp"
|
10
10
|
#include "duckdb/parser/expression/subquery_expression.hpp"
|
11
|
+
#include "duckdb/planner/expression/bound_cast_expression.hpp"
|
12
|
+
#include "duckdb/planner/expression/bound_columnref_expression.hpp"
|
11
13
|
#include "duckdb/parser/parsed_data/create_index_info.hpp"
|
12
14
|
#include "duckdb/parser/parsed_data/create_macro_info.hpp"
|
13
15
|
#include "duckdb/parser/parsed_data/create_view_info.hpp"
|
@@ -24,6 +26,7 @@
|
|
24
26
|
#include "duckdb/planner/operator/logical_create_table.hpp"
|
25
27
|
#include "duckdb/planner/operator/logical_get.hpp"
|
26
28
|
#include "duckdb/planner/operator/logical_distinct.hpp"
|
29
|
+
#include "duckdb/planner/operator/logical_projection.hpp"
|
27
30
|
#include "duckdb/planner/parsed_data/bound_create_table_info.hpp"
|
28
31
|
#include "duckdb/planner/query_node/bound_select_node.hpp"
|
29
32
|
#include "duckdb/planner/tableref/bound_basetableref.hpp"
|
@@ -605,41 +608,27 @@ BoundStatement Binder::Bind(CreateStatement &stmt) {
|
|
605
608
|
}
|
606
609
|
case CatalogType::TYPE_ENTRY: {
|
607
610
|
auto &schema = BindCreateSchema(*stmt.info);
|
608
|
-
auto &create_type_info =
|
611
|
+
auto &create_type_info = stmt.info->Cast<CreateTypeInfo>();
|
609
612
|
result.plan = make_uniq<LogicalCreate>(LogicalOperatorType::LOGICAL_CREATE_TYPE, std::move(stmt.info), &schema);
|
610
613
|
if (create_type_info.query) {
|
611
614
|
// CREATE TYPE mood AS ENUM (SELECT 'happy')
|
612
|
-
auto &select_stmt = create_type_info.query->Cast<SelectStatement>();
|
613
|
-
auto &query_node = *select_stmt.node;
|
614
|
-
|
615
|
-
// We always add distinct modifier implicitly
|
616
|
-
bool need_to_add = true;
|
617
|
-
if (!query_node.modifiers.empty()) {
|
618
|
-
if (query_node.modifiers[0]->type == ResultModifierType::DISTINCT_MODIFIER) {
|
619
|
-
// There are cases where the same column is grouped repeatedly
|
620
|
-
// CREATE TYPE mood AS ENUM (SELECT DISTINCT ON(x) x FROM test);
|
621
|
-
// When we push into a constant expression
|
622
|
-
// => CREATE TYPE mood AS ENUM (SELECT DISTINCT ON(x, x) x FROM test);
|
623
|
-
auto &distinct_modifier = (DistinctModifier &)*query_node.modifiers[0];
|
624
|
-
if (distinct_modifier.distinct_on_targets.empty()) {
|
625
|
-
need_to_add = false;
|
626
|
-
}
|
627
|
-
}
|
628
|
-
}
|
629
|
-
|
630
|
-
// Add distinct modifier
|
631
|
-
if (need_to_add) {
|
632
|
-
auto distinct_modifier = make_uniq<DistinctModifier>();
|
633
|
-
query_node.modifiers.emplace(query_node.modifiers.begin(), std::move(distinct_modifier));
|
634
|
-
}
|
635
|
-
|
636
615
|
auto query_obj = Bind(*create_type_info.query);
|
637
616
|
auto query = std::move(query_obj.plan);
|
638
617
|
|
639
618
|
auto &sql_types = query_obj.types;
|
640
|
-
if (sql_types.size() != 1
|
619
|
+
if (sql_types.size() != 1) {
|
641
620
|
// add cast expression?
|
642
|
-
throw BinderException("The query must return
|
621
|
+
throw BinderException("The query must return a single column");
|
622
|
+
}
|
623
|
+
if (sql_types[0].id() != LogicalType::VARCHAR) {
|
624
|
+
// push a projection casting to varchar
|
625
|
+
vector<unique_ptr<Expression>> select_list;
|
626
|
+
auto ref = make_uniq<BoundColumnRefExpression>(sql_types[0], query->GetColumnBindings()[0]);
|
627
|
+
auto cast_expr = BoundCastExpression::AddCastToType(context, std::move(ref), LogicalType::VARCHAR);
|
628
|
+
select_list.push_back(std::move(cast_expr));
|
629
|
+
auto proj = make_uniq<LogicalProjection>(GenerateTableIndex(), std::move(select_list));
|
630
|
+
proj->AddChild(std::move(query));
|
631
|
+
query = std::move(proj);
|
643
632
|
}
|
644
633
|
|
645
634
|
result.plan->AddChild(std::move(query));
|
@@ -660,7 +649,7 @@ BoundStatement Binder::Bind(CreateStatement &stmt) {
|
|
660
649
|
}
|
661
650
|
case CatalogType::DATABASE_ENTRY: {
|
662
651
|
// not supported in DuckDB yet but allow extensions to intercept and implement this functionality
|
663
|
-
auto &base =
|
652
|
+
auto &base = stmt.info->Cast<CreateDatabaseInfo>();
|
664
653
|
string database_name = base.name;
|
665
654
|
string source_path = base.path;
|
666
655
|
|
@@ -128,11 +128,6 @@ int (*instantiate_format_float)(double, int, internal::float_specs,
|
|
128
128
|
internal::buffer<char>&) =
|
129
129
|
internal::format_float;
|
130
130
|
|
131
|
-
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
132
|
-
template FMT_API internal::locale_ref::locale_ref(const std::locale& loc);
|
133
|
-
template FMT_API std::locale internal::locale_ref::get<std::locale>() const;
|
134
|
-
#endif
|
135
|
-
|
136
131
|
// Explicit instantiations for char.
|
137
132
|
|
138
133
|
template FMT_API std::string internal::grouping_impl<char>(locale_ref);
|
@@ -62,15 +62,9 @@
|
|
62
62
|
|
63
63
|
// Check if relaxed C++14 constexpr is supported.
|
64
64
|
// GCC doesn't allow throw in constexpr until version 6 (bug 67371).
|
65
|
-
#ifndef FMT_USE_CONSTEXPR
|
66
|
-
# define FMT_USE_CONSTEXPR \
|
67
|
-
(FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || \
|
68
|
-
(FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) && \
|
69
|
-
!FMT_NVCC
|
70
|
-
#endif
|
71
65
|
#if FMT_USE_CONSTEXPR
|
72
|
-
# define FMT_CONSTEXPR
|
73
|
-
# define FMT_CONSTEXPR_DECL
|
66
|
+
# define FMT_CONSTEXPR inline
|
67
|
+
# define FMT_CONSTEXPR_DECL
|
74
68
|
#else
|
75
69
|
# define FMT_CONSTEXPR inline
|
76
70
|
# define FMT_CONSTEXPR_DECL
|
@@ -323,6 +317,10 @@ template <typename Char> class basic_string_view {
|
|
323
317
|
size_ -= n;
|
324
318
|
}
|
325
319
|
|
320
|
+
std::string to_string() {
|
321
|
+
return std::string((char *) data(), size());
|
322
|
+
}
|
323
|
+
|
326
324
|
// Lexicographically compare this string reference to other.
|
327
325
|
int compare(basic_string_view other) const {
|
328
326
|
size_t str_size = size_ < other.size_ ? size_ : other.size_;
|
@@ -416,7 +414,7 @@ template <typename S>
|
|
416
414
|
struct is_compile_string : std::is_base_of<compile_string, S> {};
|
417
415
|
|
418
416
|
template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
|
419
|
-
|
417
|
+
FMT_CONSTEXPR basic_string_view<typename S::char_type> to_string_view(const S& s) {
|
420
418
|
return s;
|
421
419
|
}
|
422
420
|
|
@@ -442,7 +440,7 @@ struct error_handler {
|
|
442
440
|
FMT_CONSTEXPR error_handler(const error_handler&) = default;
|
443
441
|
|
444
442
|
// This function is intentionally not constexpr to give a compile-time error.
|
445
|
-
FMT_NORETURN FMT_API void on_error(
|
443
|
+
FMT_NORETURN FMT_API void on_error(std::string message);
|
446
444
|
};
|
447
445
|
} // namespace internal
|
448
446
|
|
@@ -520,7 +518,7 @@ class basic_format_parse_context : private ErrorHandler {
|
|
520
518
|
|
521
519
|
FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {}
|
522
520
|
|
523
|
-
FMT_CONSTEXPR void on_error(
|
521
|
+
FMT_CONSTEXPR void on_error(std::string message) {
|
524
522
|
ErrorHandler::on_error(message);
|
525
523
|
}
|
526
524
|
|
@@ -1158,7 +1156,7 @@ template <typename OutputIt, typename Char> class basic_format_context {
|
|
1158
1156
|
format_arg arg(basic_string_view<char_type> name);
|
1159
1157
|
|
1160
1158
|
internal::error_handler error_handler() { return {}; }
|
1161
|
-
void on_error(
|
1159
|
+
void on_error(std::string message) { error_handler().on_error(message); }
|
1162
1160
|
|
1163
1161
|
// Returns an iterator to the beginning of the output range.
|
1164
1162
|
iterator out() { return out_; }
|
@@ -17,10 +17,6 @@
|
|
17
17
|
#include <cstdarg>
|
18
18
|
#include <cstring> // for std::memmove
|
19
19
|
#include <cwchar>
|
20
|
-
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
21
|
-
# include <locale>
|
22
|
-
#endif
|
23
|
-
|
24
20
|
#if FMT_EXCEPTIONS
|
25
21
|
# define FMT_TRY try
|
26
22
|
# define FMT_CATCH(x) catch (x)
|
@@ -162,45 +158,18 @@ FMT_FUNC void report_error(format_func func, int error_code,
|
|
162
158
|
}
|
163
159
|
} // namespace internal
|
164
160
|
|
165
|
-
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
166
|
-
namespace internal {
|
167
|
-
|
168
|
-
template <typename Locale>
|
169
|
-
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
|
170
|
-
static_assert(std::is_same<Locale, std::locale>::value, "");
|
171
|
-
}
|
172
|
-
|
173
|
-
template <typename Locale> Locale locale_ref::get() const {
|
174
|
-
static_assert(std::is_same<Locale, std::locale>::value, "");
|
175
|
-
return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();
|
176
|
-
}
|
177
|
-
|
178
|
-
template <typename Char> FMT_FUNC std::string grouping_impl(locale_ref loc) {
|
179
|
-
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>()).grouping();
|
180
|
-
}
|
181
|
-
template <typename Char> FMT_FUNC Char thousands_sep_impl(locale_ref loc) {
|
182
|
-
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
183
|
-
.thousands_sep();
|
184
|
-
}
|
185
|
-
template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {
|
186
|
-
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
187
|
-
.decimal_point();
|
188
|
-
}
|
189
|
-
} // namespace internal
|
190
|
-
#else
|
191
161
|
template <typename Char>
|
192
162
|
FMT_FUNC std::string internal::grouping_impl(locale_ref) {
|
193
163
|
return "\03";
|
194
164
|
}
|
195
165
|
template <typename Char>
|
196
166
|
FMT_FUNC Char internal::thousands_sep_impl(locale_ref) {
|
197
|
-
return
|
167
|
+
return ',';
|
198
168
|
}
|
199
169
|
template <typename Char>
|
200
170
|
FMT_FUNC Char internal::decimal_point_impl(locale_ref) {
|
201
171
|
return '.';
|
202
172
|
}
|
203
|
-
#endif
|
204
173
|
|
205
174
|
namespace internal {
|
206
175
|
|
@@ -1203,7 +1172,7 @@ template <> struct formatter<internal::bigint> {
|
|
1203
1172
|
}
|
1204
1173
|
};
|
1205
1174
|
|
1206
|
-
FMT_FUNC void internal::error_handler::on_error(
|
1175
|
+
FMT_FUNC void internal::error_handler::on_error(std::string message) {
|
1207
1176
|
FMT_THROW(duckdb::Exception(message));
|
1208
1177
|
}
|
1209
1178
|
|
@@ -951,6 +951,7 @@ template <typename Char> struct basic_format_specs {
|
|
951
951
|
sign_t sign : 3;
|
952
952
|
bool alt : 1; // Alternate form ('#').
|
953
953
|
internal::fill_t<Char> fill;
|
954
|
+
char thousands;
|
954
955
|
|
955
956
|
constexpr basic_format_specs()
|
956
957
|
: width(0),
|
@@ -959,7 +960,8 @@ template <typename Char> struct basic_format_specs {
|
|
959
960
|
align(align::none),
|
960
961
|
sign(sign::none),
|
961
962
|
alt(false),
|
962
|
-
fill(internal::fill_t<Char>::make())
|
963
|
+
fill(internal::fill_t<Char>::make()),
|
964
|
+
thousands('\0'){}
|
963
965
|
};
|
964
966
|
|
965
967
|
using format_specs = basic_format_specs<char>;
|
@@ -1124,9 +1126,13 @@ int snprintf_float(T value, int precision, float_specs specs,
|
|
1124
1126
|
template <typename T> T promote_float(T value) { return value; }
|
1125
1127
|
inline double promote_float(float value) { return value; }
|
1126
1128
|
|
1127
|
-
template <typename Handler>
|
1128
|
-
FMT_CONSTEXPR void handle_int_type_spec(
|
1129
|
-
|
1129
|
+
template <typename Spec, typename Handler>
|
1130
|
+
FMT_CONSTEXPR void handle_int_type_spec(const Spec& specs, Handler&& handler) {
|
1131
|
+
if (specs.thousands != '\0') {
|
1132
|
+
handler.on_num();
|
1133
|
+
return;
|
1134
|
+
}
|
1135
|
+
switch (specs.type) {
|
1130
1136
|
case 0:
|
1131
1137
|
case 'd':
|
1132
1138
|
handler.on_dec();
|
@@ -1143,17 +1149,24 @@ FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) {
|
|
1143
1149
|
handler.on_oct();
|
1144
1150
|
break;
|
1145
1151
|
case 'n':
|
1152
|
+
case 'l':
|
1153
|
+
case 'L':
|
1146
1154
|
handler.on_num();
|
1147
1155
|
break;
|
1148
1156
|
default:
|
1149
|
-
handler.on_error();
|
1157
|
+
handler.on_error("Invalid type specifier \"" + std::string(1, specs.type) + "\" for formatting a value of type int");
|
1150
1158
|
}
|
1151
1159
|
}
|
1152
1160
|
|
1153
1161
|
template <typename ErrorHandler = error_handler, typename Char>
|
1154
1162
|
FMT_CONSTEXPR float_specs parse_float_type_spec(
|
1155
1163
|
const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
|
1164
|
+
|
1156
1165
|
auto result = float_specs();
|
1166
|
+
if (specs.thousands != '\0') {
|
1167
|
+
eh.on_error("Thousand separators are not supported for floating point numbers");
|
1168
|
+
return result;
|
1169
|
+
}
|
1157
1170
|
result.trailing_zeros = specs.alt;
|
1158
1171
|
switch (specs.type) {
|
1159
1172
|
case 0:
|
@@ -1193,10 +1206,12 @@ FMT_CONSTEXPR float_specs parse_float_type_spec(
|
|
1193
1206
|
result.format = float_format::hex;
|
1194
1207
|
break;
|
1195
1208
|
case 'n':
|
1209
|
+
case 'l':
|
1210
|
+
case 'L':
|
1196
1211
|
result.locale = true;
|
1197
1212
|
break;
|
1198
1213
|
default:
|
1199
|
-
eh.on_error("
|
1214
|
+
eh.on_error("Invalid type specifier \"" + std::string(1, specs.type) + "\" for formatting a value of type float");
|
1200
1215
|
break;
|
1201
1216
|
}
|
1202
1217
|
return result;
|
@@ -1219,17 +1234,17 @@ FMT_CONSTEXPR void handle_cstring_type_spec(Char spec, Handler&& handler) {
|
|
1219
1234
|
else if (spec == 'p')
|
1220
1235
|
handler.on_pointer();
|
1221
1236
|
else
|
1222
|
-
handler.on_error("
|
1237
|
+
handler.on_error("Invalid type specifier \"" + std::string(1, spec) + "\" for formatting a value of type string");
|
1223
1238
|
}
|
1224
1239
|
|
1225
1240
|
template <typename Char, typename ErrorHandler>
|
1226
1241
|
FMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler&& eh) {
|
1227
|
-
if (spec != 0 && spec != 's') eh.on_error("
|
1242
|
+
if (spec != 0 && spec != 's') eh.on_error("Invalid type specifier \"" + std::string(1, spec) + "\" for formatting a value of type string");
|
1228
1243
|
}
|
1229
1244
|
|
1230
1245
|
template <typename Char, typename ErrorHandler>
|
1231
1246
|
FMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler&& eh) {
|
1232
|
-
if (spec != 0 && spec != 'p') eh.on_error("
|
1247
|
+
if (spec != 0 && spec != 'p') eh.on_error("Invalid type specifier \"" + std::string(1, spec) + "\" for formatting a value of type pointer");
|
1233
1248
|
}
|
1234
1249
|
|
1235
1250
|
template <typename ErrorHandler> class int_type_checker : private ErrorHandler {
|
@@ -1242,8 +1257,8 @@ template <typename ErrorHandler> class int_type_checker : private ErrorHandler {
|
|
1242
1257
|
FMT_CONSTEXPR void on_oct() {}
|
1243
1258
|
FMT_CONSTEXPR void on_num() {}
|
1244
1259
|
|
1245
|
-
FMT_CONSTEXPR void on_error() {
|
1246
|
-
ErrorHandler::on_error(
|
1260
|
+
FMT_CONSTEXPR void on_error(std::string error) {
|
1261
|
+
ErrorHandler::on_error(error);
|
1247
1262
|
}
|
1248
1263
|
};
|
1249
1264
|
|
@@ -1500,7 +1515,7 @@ template <typename Range> class basic_writer {
|
|
1500
1515
|
void on_num() {
|
1501
1516
|
std::string groups = grouping<char_type>(writer.locale_);
|
1502
1517
|
if (groups.empty()) return on_dec();
|
1503
|
-
auto sep =
|
1518
|
+
auto sep = specs.thousands;
|
1504
1519
|
if (!sep) return on_dec();
|
1505
1520
|
int num_digits = count_digits(abs_value);
|
1506
1521
|
int size = num_digits;
|
@@ -1514,11 +1529,11 @@ template <typename Range> class basic_writer {
|
|
1514
1529
|
if (group == groups.cend())
|
1515
1530
|
size += sep_size * ((num_digits - 1) / groups.back());
|
1516
1531
|
writer.write_int(size, get_prefix(), specs,
|
1517
|
-
num_writer{abs_value, size, groups, sep});
|
1532
|
+
num_writer{abs_value, size, groups, static_cast<char_type>(sep)});
|
1518
1533
|
}
|
1519
1534
|
|
1520
|
-
FMT_NORETURN void on_error() {
|
1521
|
-
FMT_THROW(duckdb::Exception(
|
1535
|
+
FMT_NORETURN void on_error(std::string error) {
|
1536
|
+
FMT_THROW(duckdb::Exception(error));
|
1522
1537
|
}
|
1523
1538
|
};
|
1524
1539
|
|
@@ -1597,7 +1612,7 @@ template <typename Range> class basic_writer {
|
|
1597
1612
|
|
1598
1613
|
template <typename T, typename Spec>
|
1599
1614
|
void write_int(T value, const Spec& spec) {
|
1600
|
-
handle_int_type_spec(spec
|
1615
|
+
handle_int_type_spec(spec, int_writer<T, Spec>(*this, value, spec));
|
1601
1616
|
}
|
1602
1617
|
|
1603
1618
|
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
@@ -1958,6 +1973,10 @@ template <typename Char> class specs_setter {
|
|
1958
1973
|
FMT_CONSTEXPR void on_plus() { specs_.sign = sign::plus; }
|
1959
1974
|
FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; }
|
1960
1975
|
FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; }
|
1976
|
+
FMT_CONSTEXPR void on_comma() { specs_.thousands = ','; }
|
1977
|
+
FMT_CONSTEXPR void on_underscore() { specs_.thousands = '_'; }
|
1978
|
+
FMT_CONSTEXPR void on_single_quote() { specs_.thousands = '\''; }
|
1979
|
+
FMT_CONSTEXPR void on_thousands(char sep) { specs_.thousands = sep; }
|
1961
1980
|
FMT_CONSTEXPR void on_hash() { specs_.alt = true; }
|
1962
1981
|
|
1963
1982
|
FMT_CONSTEXPR void on_zero() {
|
@@ -2066,7 +2085,7 @@ struct auto_id {};
|
|
2066
2085
|
template <typename Context>
|
2067
2086
|
FMT_CONSTEXPR typename Context::format_arg get_arg(Context& ctx, int id) {
|
2068
2087
|
auto arg = ctx.arg(id);
|
2069
|
-
if (!arg) ctx.on_error("
|
2088
|
+
if (!arg) ctx.on_error("Argument index \"" + std::to_string(id) + "\" out of range");
|
2070
2089
|
return arg;
|
2071
2090
|
}
|
2072
2091
|
|
@@ -2092,7 +2111,7 @@ class specs_handler : public specs_setter<typename Context::char_type> {
|
|
2092
2111
|
get_arg(arg_id), context_.error_handler());
|
2093
2112
|
}
|
2094
2113
|
|
2095
|
-
void on_error(
|
2114
|
+
void on_error(std::string message) { context_.on_error(message); }
|
2096
2115
|
|
2097
2116
|
private:
|
2098
2117
|
// This is only needed for compatibility with gcc 4.4.
|
@@ -2176,7 +2195,7 @@ class dynamic_specs_handler
|
|
2176
2195
|
specs_.precision_ref = make_arg_ref(arg_id);
|
2177
2196
|
}
|
2178
2197
|
|
2179
|
-
FMT_CONSTEXPR void on_error(
|
2198
|
+
FMT_CONSTEXPR void on_error(std::string message) {
|
2180
2199
|
context_.on_error(message);
|
2181
2200
|
}
|
2182
2201
|
|
@@ -2242,7 +2261,7 @@ template <typename SpecHandler, typename Char> struct width_adapter {
|
|
2242
2261
|
handler.on_dynamic_width(id);
|
2243
2262
|
}
|
2244
2263
|
|
2245
|
-
FMT_CONSTEXPR void on_error(
|
2264
|
+
FMT_CONSTEXPR void on_error(std::string message) {
|
2246
2265
|
handler.on_error(message);
|
2247
2266
|
}
|
2248
2267
|
|
@@ -2259,7 +2278,7 @@ template <typename SpecHandler, typename Char> struct precision_adapter {
|
|
2259
2278
|
handler.on_dynamic_precision(id);
|
2260
2279
|
}
|
2261
2280
|
|
2262
|
-
FMT_CONSTEXPR void on_error(
|
2281
|
+
FMT_CONSTEXPR void on_error(std::string message) {
|
2263
2282
|
handler.on_error(message);
|
2264
2283
|
}
|
2265
2284
|
|
@@ -2370,6 +2389,24 @@ FMT_CONSTEXPR const Char* parse_format_specs(const Char* begin, const Char* end,
|
|
2370
2389
|
handler.on_space();
|
2371
2390
|
++begin;
|
2372
2391
|
break;
|
2392
|
+
case ',':
|
2393
|
+
handler.on_comma();
|
2394
|
+
++begin;
|
2395
|
+
break;
|
2396
|
+
case '_':
|
2397
|
+
handler.on_underscore();
|
2398
|
+
++begin;
|
2399
|
+
break;
|
2400
|
+
case '\'':
|
2401
|
+
handler.on_single_quote();
|
2402
|
+
++begin;
|
2403
|
+
break;
|
2404
|
+
case 't':
|
2405
|
+
++begin;
|
2406
|
+
if (begin == end) return begin;
|
2407
|
+
handler.on_thousands(*begin);
|
2408
|
+
++begin;
|
2409
|
+
break;
|
2373
2410
|
}
|
2374
2411
|
if (begin == end) return begin;
|
2375
2412
|
|
@@ -2420,7 +2457,7 @@ template <typename Handler, typename Char> struct id_adapter {
|
|
2420
2457
|
FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
|
2421
2458
|
handler.on_arg_id(id);
|
2422
2459
|
}
|
2423
|
-
FMT_CONSTEXPR void on_error(
|
2460
|
+
FMT_CONSTEXPR void on_error(std::string message) {
|
2424
2461
|
handler.on_error(message);
|
2425
2462
|
}
|
2426
2463
|
Handler& handler;
|
@@ -2524,7 +2561,7 @@ class format_string_checker {
|
|
2524
2561
|
return arg_id_ < num_args ? parse_funcs_[arg_id_](context_) : begin;
|
2525
2562
|
}
|
2526
2563
|
|
2527
|
-
FMT_CONSTEXPR void on_error(
|
2564
|
+
FMT_CONSTEXPR void on_error(std::string message) {
|
2528
2565
|
context_.on_error(message);
|
2529
2566
|
}
|
2530
2567
|
|
@@ -2889,7 +2926,7 @@ typename basic_format_context<Range, Char>::format_arg
|
|
2889
2926
|
basic_format_context<Range, Char>::arg(basic_string_view<char_type> name) {
|
2890
2927
|
map_.init(args_);
|
2891
2928
|
format_arg arg = map_.find(name);
|
2892
|
-
if (arg.type() == internal::none_type) this->on_error("
|
2929
|
+
if (arg.type() == internal::none_type) this->on_error("Argument with name \"" + name.to_string() + "\" not found, did you mean to use it as a format specifier (e.g. {:" + name.to_string() + "}");
|
2893
2930
|
return arg;
|
2894
2931
|
}
|
2895
2932
|
|
@@ -363,7 +363,7 @@ template <typename OutputIt, typename Char> class basic_printf_context {
|
|
363
363
|
|
364
364
|
basic_format_parse_context<Char>& parse_context() { return parse_ctx_; }
|
365
365
|
|
366
|
-
FMT_CONSTEXPR void on_error(
|
366
|
+
FMT_CONSTEXPR void on_error(std::string message) {
|
367
367
|
parse_ctx_.on_error(message);
|
368
368
|
}
|
369
369
|
|
@@ -393,6 +393,15 @@ void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs,
|
|
393
393
|
case '#':
|
394
394
|
specs.alt = true;
|
395
395
|
break;
|
396
|
+
case ',':
|
397
|
+
specs.thousands = ',';
|
398
|
+
break;
|
399
|
+
case '\'':
|
400
|
+
specs.thousands = '\'';
|
401
|
+
break;
|
402
|
+
case '_':
|
403
|
+
specs.thousands = '_';
|
404
|
+
break;
|
396
405
|
default:
|
397
406
|
return;
|
398
407
|
}
|
@@ -472,6 +481,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|
472
481
|
if (arg_index == 0) on_error("argument index out of range");
|
473
482
|
|
474
483
|
// Parse precision.
|
484
|
+
bool empty_precision = false;
|
475
485
|
if (it != end && *it == '.') {
|
476
486
|
++it;
|
477
487
|
c = it != end ? *it : 0;
|
@@ -484,6 +494,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|
484
494
|
static_cast<int>(visit_format_arg(internal::printf_precision_handler(), get_arg()));
|
485
495
|
} else {
|
486
496
|
specs.precision = 0;
|
497
|
+
empty_precision = true;
|
487
498
|
}
|
488
499
|
}
|
489
500
|
|
@@ -554,6 +565,9 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|
554
565
|
break;
|
555
566
|
}
|
556
567
|
}
|
568
|
+
if (specs.type == 'd' && empty_precision) {
|
569
|
+
specs.thousands = '.';
|
570
|
+
}
|
557
571
|
|
558
572
|
start = it;
|
559
573
|
|
@@ -1171,6 +1171,7 @@ typedef struct PGPivot {
|
|
1171
1171
|
PGList *pivot_columns; /* The column names to pivot on */
|
1172
1172
|
PGList *unpivot_columns;/* The column names to unpivot */
|
1173
1173
|
PGList *pivot_value; /* The set of pivot values */
|
1174
|
+
PGNode *subquery; /* Subquery to fetch valid pivot values (if any) */
|
1174
1175
|
char *pivot_enum; /* The enum to fetch the unique values from */
|
1175
1176
|
} PGPivot;
|
1176
1177
|
|