duckdb 0.4.1-dev29.0 → 0.4.1-dev42.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
- "version": "0.4.1-dev29.0",
4
+ "version": "0.4.1-dev42.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -25536,6 +25536,11 @@ duckdb::string_t StringCast::Operation(hugeint_t input, Vector &vector) {
25536
25536
 
25537
25537
  template <>
25538
25538
  duckdb::string_t StringCast::Operation(date_t input, Vector &vector) {
25539
+ if (input == date_t::infinity()) {
25540
+ return "infinity";
25541
+ } else if (input == date_t::ninfinity()) {
25542
+ return "-infinity";
25543
+ }
25539
25544
  int32_t date[3];
25540
25545
  Date::Convert(input, date[0], date[1], date[2]);
25541
25546
 
@@ -25571,6 +25576,11 @@ duckdb::string_t StringCast::Operation(dtime_t input, Vector &vector) {
25571
25576
 
25572
25577
  template <>
25573
25578
  duckdb::string_t StringCast::Operation(timestamp_t input, Vector &vector) {
25579
+ if (input == timestamp_t::infinity()) {
25580
+ return string_t("infinity");
25581
+ } else if (input == timestamp_t::ninfinity()) {
25582
+ return string_t("-infinity");
25583
+ }
25574
25584
  date_t date_entry;
25575
25585
  dtime_t time_entry;
25576
25586
  Timestamp::Convert(input, date_entry, time_entry);
@@ -39599,7 +39609,7 @@ unique_ptr<VectorData[]> DataChunk::Orrify() {
39599
39609
  }
39600
39610
 
39601
39611
  void DataChunk::Hash(Vector &result) {
39602
- D_ASSERT(result.GetType().id() == LogicalTypeId::HASH);
39612
+ D_ASSERT(result.GetType().id() == LogicalType::HASH);
39603
39613
  VectorOperations::Hash(data[0], result, size());
39604
39614
  for (idx_t i = 1; i < ColumnCount(); i++) {
39605
39615
  VectorOperations::CombineHash(result, data[i], size());
@@ -42133,6 +42143,126 @@ dtime_t AddTimeOperator::Operation(interval_t left, dtime_t right);
42133
42143
  } // namespace duckdb
42134
42144
 
42135
42145
 
42146
+ //===----------------------------------------------------------------------===//
42147
+ // DuckDB
42148
+ //
42149
+ // duckdb/common/operator/subtract.hpp
42150
+ //
42151
+ //
42152
+ //===----------------------------------------------------------------------===//
42153
+
42154
+
42155
+
42156
+
42157
+
42158
+
42159
+ namespace duckdb {
42160
+
42161
+ struct SubtractOperator {
42162
+ template <class TA, class TB, class TR>
42163
+ static inline TR Operation(TA left, TB right) {
42164
+ return left - right;
42165
+ }
42166
+ };
42167
+
42168
+ template <>
42169
+ float SubtractOperator::Operation(float left, float right);
42170
+ template <>
42171
+ double SubtractOperator::Operation(double left, double right);
42172
+ template <>
42173
+ interval_t SubtractOperator::Operation(interval_t left, interval_t right);
42174
+ template <>
42175
+ int64_t SubtractOperator::Operation(date_t left, date_t right);
42176
+ template <>
42177
+ date_t SubtractOperator::Operation(date_t left, int32_t right);
42178
+ template <>
42179
+ date_t SubtractOperator::Operation(date_t left, interval_t right);
42180
+ template <>
42181
+ timestamp_t SubtractOperator::Operation(timestamp_t left, interval_t right);
42182
+ template <>
42183
+ interval_t SubtractOperator::Operation(timestamp_t left, timestamp_t right);
42184
+
42185
+ struct TrySubtractOperator {
42186
+ template <class TA, class TB, class TR>
42187
+ static inline bool Operation(TA left, TB right, TR &result) {
42188
+ throw InternalException("Unimplemented type for TrySubtractOperator");
42189
+ }
42190
+ };
42191
+
42192
+ template <>
42193
+ bool TrySubtractOperator::Operation(uint8_t left, uint8_t right, uint8_t &result);
42194
+ template <>
42195
+ bool TrySubtractOperator::Operation(uint16_t left, uint16_t right, uint16_t &result);
42196
+ template <>
42197
+ bool TrySubtractOperator::Operation(uint32_t left, uint32_t right, uint32_t &result);
42198
+ template <>
42199
+ bool TrySubtractOperator::Operation(uint64_t left, uint64_t right, uint64_t &result);
42200
+
42201
+ template <>
42202
+ bool TrySubtractOperator::Operation(int8_t left, int8_t right, int8_t &result);
42203
+ template <>
42204
+ bool TrySubtractOperator::Operation(int16_t left, int16_t right, int16_t &result);
42205
+ template <>
42206
+ bool TrySubtractOperator::Operation(int32_t left, int32_t right, int32_t &result);
42207
+ template <>
42208
+ bool TrySubtractOperator::Operation(int64_t left, int64_t right, int64_t &result);
42209
+ template <>
42210
+ bool TrySubtractOperator::Operation(hugeint_t left, hugeint_t right, hugeint_t &result);
42211
+
42212
+ struct SubtractOperatorOverflowCheck {
42213
+ template <class TA, class TB, class TR>
42214
+ static inline TR Operation(TA left, TB right) {
42215
+ TR result;
42216
+ if (!TrySubtractOperator::Operation(left, right, result)) {
42217
+ throw OutOfRangeException("Overflow in subtraction of %s (%d - %d)!", TypeIdToString(GetTypeId<TA>()), left,
42218
+ right);
42219
+ }
42220
+ return result;
42221
+ }
42222
+ };
42223
+
42224
+ struct TryDecimalSubtract {
42225
+ template <class TA, class TB, class TR>
42226
+ static inline bool Operation(TA left, TB right, TR &result) {
42227
+ throw InternalException("Unimplemented type for TryDecimalSubtract");
42228
+ }
42229
+ };
42230
+
42231
+ template <>
42232
+ bool TryDecimalSubtract::Operation(int16_t left, int16_t right, int16_t &result);
42233
+ template <>
42234
+ bool TryDecimalSubtract::Operation(int32_t left, int32_t right, int32_t &result);
42235
+ template <>
42236
+ bool TryDecimalSubtract::Operation(int64_t left, int64_t right, int64_t &result);
42237
+ template <>
42238
+ bool TryDecimalSubtract::Operation(hugeint_t left, hugeint_t right, hugeint_t &result);
42239
+
42240
+ struct DecimalSubtractOverflowCheck {
42241
+ template <class TA, class TB, class TR>
42242
+ static inline TR Operation(TA left, TB right) {
42243
+ TR result;
42244
+ if (!TryDecimalSubtract::Operation<TA, TB, TR>(left, right, result)) {
42245
+ throw OutOfRangeException("Overflow in subtract of DECIMAL(18) (%d - %d). You might want to add an "
42246
+ "explicit cast to a bigger decimal.",
42247
+ left, right);
42248
+ }
42249
+ return result;
42250
+ }
42251
+ };
42252
+
42253
+ template <>
42254
+ hugeint_t DecimalSubtractOverflowCheck::Operation(hugeint_t left, hugeint_t right);
42255
+
42256
+ struct SubtractTimeOperator {
42257
+ template <class TA, class TB, class TR>
42258
+ static TR Operation(TA left, TB right);
42259
+ };
42260
+
42261
+ template <>
42262
+ dtime_t SubtractTimeOperator::Operation(dtime_t left, interval_t right);
42263
+
42264
+ } // namespace duckdb
42265
+
42136
42266
 
42137
42267
 
42138
42268
  namespace duckdb {
@@ -42410,6 +42540,7 @@ int64_t Interval::GetNanoseconds(const interval_t &val) {
42410
42540
  }
42411
42541
 
42412
42542
  interval_t Interval::GetAge(timestamp_t timestamp_1, timestamp_t timestamp_2) {
42543
+ D_ASSERT(Timestamp::IsFinite(timestamp_1) && Timestamp::IsFinite(timestamp_2));
42413
42544
  date_t date1, date2;
42414
42545
  dtime_t time1, time2;
42415
42546
 
@@ -42499,9 +42630,15 @@ interval_t Interval::GetAge(timestamp_t timestamp_1, timestamp_t timestamp_2) {
42499
42630
  }
42500
42631
 
42501
42632
  interval_t Interval::GetDifference(timestamp_t timestamp_1, timestamp_t timestamp_2) {
42633
+ if (!Timestamp::IsFinite(timestamp_1) || !Timestamp::IsFinite(timestamp_2)) {
42634
+ throw InvalidInputException("Cannot subtract infinite timestamps");
42635
+ }
42502
42636
  const auto us_1 = Timestamp::GetEpochMicroSeconds(timestamp_1);
42503
42637
  const auto us_2 = Timestamp::GetEpochMicroSeconds(timestamp_2);
42504
- const auto delta_us = us_1 - us_2;
42638
+ int64_t delta_us;
42639
+ if (!TrySubtractOperator::Operation(us_1, us_2, delta_us)) {
42640
+ throw ConversionException("Timestamp difference is out of bounds");
42641
+ }
42505
42642
  return FromMicro(delta_us);
42506
42643
  }
42507
42644
 
@@ -44706,8 +44843,6 @@ Value Value::Numeric(const LogicalType &type, int64_t value) {
44706
44843
  return Value((float)value);
44707
44844
  case LogicalTypeId::DOUBLE:
44708
44845
  return Value((double)value);
44709
- case LogicalTypeId::HASH:
44710
- return Value::HASH(value);
44711
44846
  case LogicalTypeId::POINTER:
44712
44847
  return Value::POINTER(value);
44713
44848
  case LogicalTypeId::DATE:
@@ -45098,8 +45233,6 @@ string Value::ToString() const {
45098
45233
  return Blob::ToString(string_t(str_value));
45099
45234
  case LogicalTypeId::POINTER:
45100
45235
  return to_string(value_.pointer);
45101
- case LogicalTypeId::HASH:
45102
- return to_string(value_.hash);
45103
45236
  case LogicalTypeId::STRUCT: {
45104
45237
  string ret = "{";
45105
45238
  auto &child_types = StructType::GetChildTypes(type_);
@@ -46218,8 +46351,6 @@ Value Vector::GetValue(const Vector &v_p, idx_t index_p) {
46218
46351
  throw InternalException("ENUM can only have unsigned integers as physical types");
46219
46352
  }
46220
46353
  }
46221
- case LogicalTypeId::HASH:
46222
- return Value::HASH(((hash_t *)data)[index]);
46223
46354
  case LogicalTypeId::POINTER:
46224
46355
  return Value::POINTER(((uintptr_t *)data)[index]);
46225
46356
  case LogicalTypeId::FLOAT:
@@ -46775,7 +46906,7 @@ void Vector::Verify(Vector &vector_p, const SelectionVector &sel_p, idx_t count)
46775
46906
  D_ASSERT(child_types.size() == children.size());
46776
46907
  for (idx_t child_idx = 0; child_idx < children.size(); child_idx++) {
46777
46908
  D_ASSERT(children[child_idx]->GetType() == child_types[child_idx].second);
46778
- children[child_idx]->Verify(count);
46909
+ Vector::Verify(*children[child_idx], sel_p, count);
46779
46910
  if (vtype == VectorType::CONSTANT_VECTOR) {
46780
46911
  D_ASSERT(children[child_idx]->GetVectorType() == VectorType::CONSTANT_VECTOR);
46781
46912
  if (ConstantVector::IsNull(*vector)) {
@@ -47611,9 +47742,6 @@ PhysicalType LogicalType::GetInternalType() {
47611
47742
  return PhysicalType::STRUCT;
47612
47743
  case LogicalTypeId::LIST:
47613
47744
  return PhysicalType::LIST;
47614
- case LogicalTypeId::HASH:
47615
- static_assert(sizeof(hash_t) == sizeof(uint64_t), "Hash must be uint64_t");
47616
- return PhysicalType::UINT64;
47617
47745
  case LogicalTypeId::POINTER:
47618
47746
  // LCOV_EXCL_START
47619
47747
  if (sizeof(uintptr_t) == sizeof(uint32_t)) {
@@ -47922,8 +48050,6 @@ string LogicalTypeIdToString(LogicalTypeId id) {
47922
48050
  return "LIST";
47923
48051
  case LogicalTypeId::MAP:
47924
48052
  return "MAP";
47925
- case LogicalTypeId::HASH:
47926
- return "HASH";
47927
48053
  case LogicalTypeId::POINTER:
47928
48054
  return "POINTER";
47929
48055
  case LogicalTypeId::TABLE:
@@ -52564,7 +52690,7 @@ static inline void ListLoopHash(Vector &input, Vector &hashes, const SelectionVe
52564
52690
 
52565
52691
  template <bool HAS_RSEL>
52566
52692
  static inline void HashTypeSwitch(Vector &input, Vector &result, const SelectionVector *rsel, idx_t count) {
52567
- D_ASSERT(result.GetType().id() == LogicalTypeId::HASH);
52693
+ D_ASSERT(result.GetType().id() == LogicalType::HASH);
52568
52694
  switch (input.GetType().InternalType()) {
52569
52695
  case PhysicalType::BOOL:
52570
52696
  case PhysicalType::INT8:
@@ -52696,7 +52822,7 @@ void TemplatedLoopCombineHash(Vector &input, Vector &hashes, const SelectionVect
52696
52822
 
52697
52823
  template <bool HAS_RSEL>
52698
52824
  static inline void CombineHashTypeSwitch(Vector &hashes, Vector &input, const SelectionVector *rsel, idx_t count) {
52699
- D_ASSERT(hashes.GetType().id() == LogicalTypeId::HASH);
52825
+ D_ASSERT(hashes.GetType().id() == LogicalType::HASH);
52700
52826
  switch (input.GetType().InternalType()) {
52701
52827
  case PhysicalType::BOOL:
52702
52828
  case PhysicalType::INT8:
@@ -57647,7 +57773,7 @@ void JoinHashTable::Build(DataChunk &keys, DataChunk &payload) {
57647
57773
  }
57648
57774
 
57649
57775
  void JoinHashTable::InsertHashes(Vector &hashes, idx_t count, data_ptr_t key_locations[]) {
57650
- D_ASSERT(hashes.GetType().id() == LogicalTypeId::HASH);
57776
+ D_ASSERT(hashes.GetType().id() == LogicalType::HASH);
57651
57777
 
57652
57778
  // use bitmask to get position in array
57653
57779
  ApplyBitmask(hashes, count);
@@ -60326,7 +60452,7 @@ static void ScanSortedPartition(WindowOperatorState &state, ChunkCollection &inp
60326
60452
  }
60327
60453
 
60328
60454
  static void HashChunk(counts_t &counts, DataChunk &hash_chunk, DataChunk &sort_chunk, const idx_t partition_cols) {
60329
- const vector<LogicalType> hash_types(1, LogicalTypeId::HASH);
60455
+ const vector<LogicalType> hash_types(1, LogicalType::HASH);
60330
60456
  hash_chunk.Initialize(hash_types);
60331
60457
  hash_chunk.SetCardinality(sort_chunk);
60332
60458
  auto &hash_vector = hash_chunk.data[0];
@@ -74935,125 +75061,6 @@ void PhysicalOperator::Verify() {
74935
75061
 
74936
75062
  } // namespace duckdb
74937
75063
 
74938
- //===----------------------------------------------------------------------===//
74939
- // DuckDB
74940
- //
74941
- // duckdb/common/operator/subtract.hpp
74942
- //
74943
- //
74944
- //===----------------------------------------------------------------------===//
74945
-
74946
-
74947
-
74948
-
74949
-
74950
-
74951
- namespace duckdb {
74952
-
74953
- struct SubtractOperator {
74954
- template <class TA, class TB, class TR>
74955
- static inline TR Operation(TA left, TB right) {
74956
- return left - right;
74957
- }
74958
- };
74959
-
74960
- template <>
74961
- float SubtractOperator::Operation(float left, float right);
74962
- template <>
74963
- double SubtractOperator::Operation(double left, double right);
74964
- template <>
74965
- interval_t SubtractOperator::Operation(interval_t left, interval_t right);
74966
- template <>
74967
- int64_t SubtractOperator::Operation(date_t left, date_t right);
74968
- template <>
74969
- date_t SubtractOperator::Operation(date_t left, int32_t right);
74970
- template <>
74971
- date_t SubtractOperator::Operation(date_t left, interval_t right);
74972
- template <>
74973
- timestamp_t SubtractOperator::Operation(timestamp_t left, interval_t right);
74974
- template <>
74975
- interval_t SubtractOperator::Operation(timestamp_t left, timestamp_t right);
74976
-
74977
- struct TrySubtractOperator {
74978
- template <class TA, class TB, class TR>
74979
- static inline bool Operation(TA left, TB right, TR &result) {
74980
- throw InternalException("Unimplemented type for TrySubtractOperator");
74981
- }
74982
- };
74983
-
74984
- template <>
74985
- bool TrySubtractOperator::Operation(uint8_t left, uint8_t right, uint8_t &result);
74986
- template <>
74987
- bool TrySubtractOperator::Operation(uint16_t left, uint16_t right, uint16_t &result);
74988
- template <>
74989
- bool TrySubtractOperator::Operation(uint32_t left, uint32_t right, uint32_t &result);
74990
- template <>
74991
- bool TrySubtractOperator::Operation(uint64_t left, uint64_t right, uint64_t &result);
74992
-
74993
- template <>
74994
- bool TrySubtractOperator::Operation(int8_t left, int8_t right, int8_t &result);
74995
- template <>
74996
- bool TrySubtractOperator::Operation(int16_t left, int16_t right, int16_t &result);
74997
- template <>
74998
- bool TrySubtractOperator::Operation(int32_t left, int32_t right, int32_t &result);
74999
- template <>
75000
- bool TrySubtractOperator::Operation(int64_t left, int64_t right, int64_t &result);
75001
- template <>
75002
- bool TrySubtractOperator::Operation(hugeint_t left, hugeint_t right, hugeint_t &result);
75003
-
75004
- struct SubtractOperatorOverflowCheck {
75005
- template <class TA, class TB, class TR>
75006
- static inline TR Operation(TA left, TB right) {
75007
- TR result;
75008
- if (!TrySubtractOperator::Operation(left, right, result)) {
75009
- throw OutOfRangeException("Overflow in subtraction of %s (%d - %d)!", TypeIdToString(GetTypeId<TA>()), left,
75010
- right);
75011
- }
75012
- return result;
75013
- }
75014
- };
75015
-
75016
- struct TryDecimalSubtract {
75017
- template <class TA, class TB, class TR>
75018
- static inline bool Operation(TA left, TB right, TR &result) {
75019
- throw InternalException("Unimplemented type for TryDecimalSubtract");
75020
- }
75021
- };
75022
-
75023
- template <>
75024
- bool TryDecimalSubtract::Operation(int16_t left, int16_t right, int16_t &result);
75025
- template <>
75026
- bool TryDecimalSubtract::Operation(int32_t left, int32_t right, int32_t &result);
75027
- template <>
75028
- bool TryDecimalSubtract::Operation(int64_t left, int64_t right, int64_t &result);
75029
- template <>
75030
- bool TryDecimalSubtract::Operation(hugeint_t left, hugeint_t right, hugeint_t &result);
75031
-
75032
- struct DecimalSubtractOverflowCheck {
75033
- template <class TA, class TB, class TR>
75034
- static inline TR Operation(TA left, TB right) {
75035
- TR result;
75036
- if (!TryDecimalSubtract::Operation<TA, TB, TR>(left, right, result)) {
75037
- throw OutOfRangeException("Overflow in subtract of DECIMAL(18) (%d - %d). You might want to add an "
75038
- "explicit cast to a bigger decimal.",
75039
- left, right);
75040
- }
75041
- return result;
75042
- }
75043
- };
75044
-
75045
- template <>
75046
- hugeint_t DecimalSubtractOverflowCheck::Operation(hugeint_t left, hugeint_t right);
75047
-
75048
- struct SubtractTimeOperator {
75049
- template <class TA, class TB, class TR>
75050
- static TR Operation(TA left, TB right);
75051
- };
75052
-
75053
- template <>
75054
- dtime_t SubtractTimeOperator::Operation(dtime_t left, interval_t right);
75055
-
75056
- } // namespace duckdb
75057
75064
 
75058
75065
 
75059
75066
 
@@ -93029,6 +93036,9 @@ string StrfTimeFormat::Format(timestamp_t timestamp, const string &format_str) {
93029
93036
  }
93030
93037
 
93031
93038
  string StrTimeFormat::ParseFormatSpecifier(const string &format_string, StrTimeFormat &format) {
93039
+ if (format_string.empty()) {
93040
+ return "Empty format string";
93041
+ }
93032
93042
  format.specifiers.clear();
93033
93043
  format.literals.clear();
93034
93044
  format.numeric_width.clear();
@@ -93407,6 +93417,7 @@ bool StrpTimeFormat::Parse(string_t str, ParseResult &result) {
93407
93417
  uint64_t yearday = 0;
93408
93418
 
93409
93419
  for (idx_t i = 0;; i++) {
93420
+ D_ASSERT(i < literals.size());
93410
93421
  // first compare the literal
93411
93422
  const auto &literal = literals[i];
93412
93423
  for (size_t l = 0; l < literal.size();) {
@@ -93797,7 +93808,10 @@ static unique_ptr<FunctionData> StrpTimeBindFunction(ClientContext &context, Sca
93797
93808
  Value options_str = ExpressionExecutor::EvaluateScalar(*arguments[1]);
93798
93809
  string format_string = options_str.ToString();
93799
93810
  StrpTimeFormat format;
93800
- if (!options_str.IsNull() && options_str.type().id() == LogicalTypeId::VARCHAR) {
93811
+ if (!options_str.IsNull()) {
93812
+ if (options_str.type().id() != LogicalTypeId::VARCHAR) {
93813
+ throw InvalidInputException("strptime format must be a string");
93814
+ }
93801
93815
  format.format_specifier = format_string;
93802
93816
  string error = StrTimeFormat::ParseFormatSpecifier(format_string, format);
93803
93817
  if (!error.empty()) {
package/src/duckdb.hpp CHANGED
@@ -11,8 +11,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
13
  #define DUCKDB_AMALGAMATION_EXTENDED 1
14
- #define DUCKDB_SOURCE_ID "b70bf98b5"
15
- #define DUCKDB_VERSION "v0.4.1-dev29"
14
+ #define DUCKDB_SOURCE_ID "1f06d609f"
15
+ #define DUCKDB_VERSION "v0.4.1-dev42"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -983,7 +983,7 @@ enum class LogicalTypeId : uint8_t {
983
983
 
984
984
  HUGEINT = 50,
985
985
  POINTER = 51,
986
- HASH = 52,
986
+ // HASH = 52, // deprecated, uses UBIGINT instead
987
987
  VALIDITY = 53,
988
988
  UUID = 54,
989
989
 
@@ -1095,7 +1095,7 @@ public:
1095
1095
  static constexpr const LogicalTypeId INTERVAL = LogicalTypeId::INTERVAL;
1096
1096
  static constexpr const LogicalTypeId HUGEINT = LogicalTypeId::HUGEINT;
1097
1097
  static constexpr const LogicalTypeId UUID = LogicalTypeId::UUID;
1098
- static constexpr const LogicalTypeId HASH = LogicalTypeId::HASH;
1098
+ static constexpr const LogicalTypeId HASH = LogicalTypeId::UBIGINT;
1099
1099
  static constexpr const LogicalTypeId POINTER = LogicalTypeId::POINTER;
1100
1100
  static constexpr const LogicalTypeId TABLE = LogicalTypeId::TABLE;
1101
1101
  static constexpr const LogicalTypeId INVALID = LogicalTypeId::INVALID;
@@ -22466,7 +22466,7 @@ protected:
22466
22466
  //! Format is literals[0], specifiers[0], literals[1], ..., specifiers[n - 1], literals[n]
22467
22467
  vector<string> literals;
22468
22468
  //! The constant size that appears in the format string
22469
- idx_t constant_size;
22469
+ idx_t constant_size = 0;
22470
22470
  //! The max numeric width of the specifier (if it is parsed as a number), or -1 if it is not a number
22471
22471
  vector<int> numeric_width;
22472
22472