duckdb 0.3.2-dev19.0 → 0.3.2-dev29.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.3.2-dev19.0",
4
+ "version": "0.3.2-dev29.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -18315,7 +18315,7 @@ struct RegexpFun {
18315
18315
 
18316
18316
  struct SubstringFun {
18317
18317
  static void RegisterFunction(BuiltinFunctions &set);
18318
- static string_t SubstringScalarFunction(Vector &result, string_t input, int32_t offset, int32_t length);
18318
+ static string_t SubstringScalarFunction(Vector &result, string_t input, int64_t offset, int64_t length);
18319
18319
  };
18320
18320
 
18321
18321
  struct PrintfFun {
@@ -37228,6 +37228,52 @@ bool Interval::GreaterThanEquals(interval_t left, interval_t right) {
37228
37228
  return GreaterThan(left, right) || Equals(left, right);
37229
37229
  }
37230
37230
 
37231
+ date_t Interval::Add(date_t left, interval_t right) {
37232
+ date_t result;
37233
+ if (right.months != 0) {
37234
+ int32_t year, month, day;
37235
+ Date::Convert(left, year, month, day);
37236
+ int32_t year_diff = right.months / Interval::MONTHS_PER_YEAR;
37237
+ year += year_diff;
37238
+ month += right.months - year_diff * Interval::MONTHS_PER_YEAR;
37239
+ if (month > Interval::MONTHS_PER_YEAR) {
37240
+ year++;
37241
+ month -= Interval::MONTHS_PER_YEAR;
37242
+ } else if (month <= 0) {
37243
+ year--;
37244
+ month += Interval::MONTHS_PER_YEAR;
37245
+ }
37246
+ day = MinValue<int32_t>(day, Date::MonthDays(year, month));
37247
+ result = Date::FromDate(year, month, day);
37248
+ } else {
37249
+ result = left;
37250
+ }
37251
+ if (right.days != 0) {
37252
+ if (!TryAddOperator::Operation(result.days, right.days, result.days)) {
37253
+ throw OutOfRangeException("Date out of range");
37254
+ }
37255
+ }
37256
+ if (right.micros != 0) {
37257
+ if (!TryAddOperator::Operation(result.days, int32_t(right.micros / Interval::MICROS_PER_DAY), result.days)) {
37258
+ throw OutOfRangeException("Date out of range");
37259
+ }
37260
+ }
37261
+ return result;
37262
+ }
37263
+
37264
+ dtime_t Interval::Add(dtime_t left, interval_t right, date_t &date) {
37265
+ int64_t diff = right.micros - ((right.micros / Interval::MICROS_PER_DAY) * Interval::MICROS_PER_DAY);
37266
+ left += diff;
37267
+ if (left.micros >= Interval::MICROS_PER_DAY) {
37268
+ left.micros -= Interval::MICROS_PER_DAY;
37269
+ date.days++;
37270
+ } else if (left.micros < 0) {
37271
+ left.micros += Interval::MICROS_PER_DAY;
37272
+ date.days--;
37273
+ }
37274
+ return left;
37275
+ }
37276
+
37231
37277
  } // namespace duckdb
37232
37278
 
37233
37279
 
@@ -61182,15 +61228,9 @@ struct BufferedCSVReaderOptions {
61182
61228
  //! Whether or not a type format is specified
61183
61229
  std::map<LogicalTypeId, bool> has_format = {{LogicalTypeId::DATE, false}, {LogicalTypeId::TIMESTAMP, false}};
61184
61230
 
61185
- std::string toString() const {
61186
- return "DELIMITER='" + delimiter + (has_delimiter ? "'" : (auto_detect ? "' (auto detected)" : "' (default)")) +
61187
- ", QUOTE='" + quote + (has_quote ? "'" : (auto_detect ? "' (auto detected)" : "' (default)")) +
61188
- ", ESCAPE='" + escape + (has_escape ? "'" : (auto_detect ? "' (auto detected)" : "' (default)")) +
61189
- ", HEADER=" + std::to_string(header) +
61190
- (has_header ? "" : (auto_detect ? " (auto detected)" : "' (default)")) +
61191
- ", SAMPLE_SIZE=" + std::to_string(sample_chunk_size * sample_chunks) +
61192
- ", ALL_VARCHAR=" + std::to_string(all_varchar);
61193
- }
61231
+ void SetDelimiter(const string &delimiter);
61232
+
61233
+ std::string ToString() const;
61194
61234
  };
61195
61235
 
61196
61236
  enum class ParserMode : uint8_t { PARSING = 0, SNIFFING_DIALECT = 1, SNIFFING_DATATYPES = 2, PARSING_HEADER = 3 };
@@ -61343,6 +61383,24 @@ private:
61343
61383
 
61344
61384
  namespace duckdb {
61345
61385
 
61386
+ void BufferedCSVReaderOptions::SetDelimiter(const string &input) {
61387
+ this->delimiter = StringUtil::Replace(input, "\\t", "\t");
61388
+ this->has_delimiter = true;
61389
+ if (input.empty()) {
61390
+ throw BinderException("DELIM or SEP must not be empty");
61391
+ }
61392
+ }
61393
+
61394
+ std::string BufferedCSVReaderOptions::ToString() const {
61395
+ return "DELIMITER='" + delimiter + (has_delimiter ? "'" : (auto_detect ? "' (auto detected)" : "' (default)")) +
61396
+ ", QUOTE='" + quote + (has_quote ? "'" : (auto_detect ? "' (auto detected)" : "' (default)")) +
61397
+ ", ESCAPE='" + escape + (has_escape ? "'" : (auto_detect ? "' (auto detected)" : "' (default)")) +
61398
+ ", HEADER=" + std::to_string(header) +
61399
+ (has_header ? "" : (auto_detect ? " (auto detected)" : "' (default)")) +
61400
+ ", SAMPLE_SIZE=" + std::to_string(sample_chunk_size * sample_chunks) +
61401
+ ", ALL_VARCHAR=" + std::to_string(all_varchar);
61402
+ }
61403
+
61346
61404
  static string GetLineNumberStr(idx_t linenr, bool linenr_estimated) {
61347
61405
  string estimated = (linenr_estimated ? string(" (estimated)") : string(""));
61348
61406
  return to_string(linenr + 1) + estimated;
@@ -62156,7 +62214,7 @@ vector<LogicalType> BufferedCSVReader::RefineTypeDetection(const vector<LogicalT
62156
62214
  if (requested_types.size() != options.num_cols) {
62157
62215
  throw InvalidInputException(
62158
62216
  "Error while determining column types: found %lld columns but expected %d. (%s)", options.num_cols,
62159
- requested_types.size(), options.toString());
62217
+ requested_types.size(), options.ToString());
62160
62218
  } else {
62161
62219
  detected_types = requested_types;
62162
62220
  }
@@ -62414,7 +62472,7 @@ in_quotes:
62414
62472
  } while (ReadBuffer(start));
62415
62473
  // still in quoted state at the end of the file, error:
62416
62474
  error_message = StringUtil::Format("Error in file \"%s\" on line %s: unterminated quotes. (%s)", options.file_path,
62417
- GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62475
+ GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62418
62476
  return false;
62419
62477
  unquote:
62420
62478
  /* state: unquote */
@@ -62444,7 +62502,7 @@ unquote:
62444
62502
  error_message = StringUtil::Format(
62445
62503
  "Error in file \"%s\" on line %s: quote should be followed by end of value, end "
62446
62504
  "of row or another quote. (%s)",
62447
- options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62505
+ options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62448
62506
  return false;
62449
62507
  }
62450
62508
  if (delimiter_pos == options.delimiter.size()) {
@@ -62461,7 +62519,7 @@ unquote:
62461
62519
  } while (ReadBuffer(start));
62462
62520
  error_message = StringUtil::Format(
62463
62521
  "Error in file \"%s\" on line %s: quote should be followed by end of value, end of row or another quote. (%s)",
62464
- options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62522
+ options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62465
62523
  return false;
62466
62524
  handle_escape:
62467
62525
  escape_pos = 0;
@@ -62476,7 +62534,7 @@ handle_escape:
62476
62534
  if (count > escape_pos && count > quote_pos) {
62477
62535
  error_message = StringUtil::Format(
62478
62536
  "Error in file \"%s\" on line %s: neither QUOTE nor ESCAPE is proceeded by ESCAPE. (%s)",
62479
- options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62537
+ options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62480
62538
  return false;
62481
62539
  }
62482
62540
  if (quote_pos == options.quote.size() || escape_pos == options.escape.size()) {
@@ -62487,7 +62545,7 @@ handle_escape:
62487
62545
  } while (ReadBuffer(start));
62488
62546
  error_message =
62489
62547
  StringUtil::Format("Error in file \"%s\" on line %s: neither QUOTE nor ESCAPE is proceeded by ESCAPE. (%s)",
62490
- options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62548
+ options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62491
62549
  return false;
62492
62550
  carriage_return:
62493
62551
  /* state: carriage_return */
@@ -62619,7 +62677,7 @@ in_quotes:
62619
62677
  } while (ReadBuffer(start));
62620
62678
  // still in quoted state at the end of the file, error:
62621
62679
  throw InvalidInputException("Error in file \"%s\" on line %s: unterminated quotes. (%s)", options.file_path,
62622
- GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62680
+ GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62623
62681
  unquote:
62624
62682
  /* state: unquote */
62625
62683
  // this state handles the state directly after we unquote
@@ -62646,7 +62704,7 @@ unquote:
62646
62704
  error_message = StringUtil::Format(
62647
62705
  "Error in file \"%s\" on line %s: quote should be followed by end of value, end of "
62648
62706
  "row or another quote. (%s)",
62649
- options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62707
+ options.file_path, GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62650
62708
  return false;
62651
62709
  }
62652
62710
  handle_escape:
@@ -62656,13 +62714,13 @@ handle_escape:
62656
62714
  if (position >= buffer_size && !ReadBuffer(start)) {
62657
62715
  error_message = StringUtil::Format(
62658
62716
  "Error in file \"%s\" on line %s: neither QUOTE nor ESCAPE is proceeded by ESCAPE. (%s)", options.file_path,
62659
- GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62717
+ GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62660
62718
  return false;
62661
62719
  }
62662
62720
  if (buffer[position] != options.quote[0] && buffer[position] != options.escape[0]) {
62663
62721
  error_message = StringUtil::Format(
62664
62722
  "Error in file \"%s\" on line %s: neither QUOTE nor ESCAPE is proceeded by ESCAPE. (%s)", options.file_path,
62665
- GetLineNumberStr(linenr, linenr_estimated).c_str(), options.toString());
62723
+ GetLineNumberStr(linenr, linenr_estimated).c_str(), options.ToString());
62666
62724
  return false;
62667
62725
  }
62668
62726
  // escape was followed by quote or escape, go back to quoted state
@@ -62802,7 +62860,7 @@ void BufferedCSVReader::AddValue(char *str_val, idx_t length, idx_t &column, vec
62802
62860
  if (column >= sql_types.size()) {
62803
62861
  throw InvalidInputException("Error on line %s: expected %lld values per row, but got more. (%s)",
62804
62862
  GetLineNumberStr(linenr, linenr_estimated).c_str(), sql_types.size(),
62805
- options.toString());
62863
+ options.ToString());
62806
62864
  }
62807
62865
 
62808
62866
  // insert the line number into the chunk
@@ -62857,7 +62915,7 @@ bool BufferedCSVReader::AddRow(DataChunk &insert_chunk, idx_t &column) {
62857
62915
  if (column < sql_types.size() && mode != ParserMode::SNIFFING_DIALECT) {
62858
62916
  throw InvalidInputException("Error on line %s: expected %lld values per row, but got %d. (%s)",
62859
62917
  GetLineNumberStr(linenr, linenr_estimated).c_str(), sql_types.size(), column,
62860
- options.toString());
62918
+ options.ToString());
62861
62919
  }
62862
62920
 
62863
62921
  if (mode == ParserMode::SNIFFING_DIALECT) {
@@ -62910,7 +62968,7 @@ void BufferedCSVReader::Flush(DataChunk &insert_chunk) {
62910
62968
  throw InvalidInputException("Error in file \"%s\" between line %llu and %llu in column \"%s\": "
62911
62969
  "file is not valid UTF8. Parser options: %s",
62912
62970
  options.file_path, linenr - parse_chunk.size(), linenr, col_name,
62913
- options.toString());
62971
+ options.ToString());
62914
62972
  }
62915
62973
  }
62916
62974
  }
@@ -62944,11 +63002,11 @@ void BufferedCSVReader::Flush(DataChunk &insert_chunk) {
62944
63002
  "(SAMPLE_SIZE=X [X rows] or SAMPLE_SIZE=-1 [all rows]), "
62945
63003
  "or skipping column conversion (ALL_VARCHAR=1)",
62946
63004
  error_message, col_name, linenr - parse_chunk.size() + 1, linenr,
62947
- options.toString());
63005
+ options.ToString());
62948
63006
  } else {
62949
63007
  throw InvalidInputException("%s between line %llu and %llu in column %s. Parser options: %s ",
62950
63008
  error_message, linenr - parse_chunk.size(), linenr, col_name,
62951
- options.toString());
63009
+ options.ToString());
62952
63010
  }
62953
63011
  }
62954
63012
  }
@@ -80743,7 +80801,7 @@ int64_t DatePart::MicrosecondsOperator::Operation(timestamp_t input) {
80743
80801
  template <>
80744
80802
  int64_t DatePart::MicrosecondsOperator::Operation(interval_t input) {
80745
80803
  // remove everything but the second & microsecond part
80746
- return input.micros;
80804
+ return input.micros % Interval::MICROS_PER_MINUTE;
80747
80805
  }
80748
80806
 
80749
80807
  template <>
@@ -80823,8 +80881,17 @@ int64_t DatePart::EpochOperator::Operation(timestamp_t input) {
80823
80881
 
80824
80882
  template <>
80825
80883
  int64_t DatePart::EpochOperator::Operation(interval_t input) {
80826
- auto secs = SecondsOperator::Operation<interval_t, int64_t>(input);
80827
- return (input.months * Interval::DAYS_PER_MONTH + input.days) * Interval::SECS_PER_DAY + secs;
80884
+ int64_t interval_years = input.months / Interval::MONTHS_PER_YEAR;
80885
+ int64_t interval_days;
80886
+ interval_days = Interval::DAYS_PER_YEAR * interval_years;
80887
+ interval_days += Interval::DAYS_PER_MONTH * (input.months % Interval::MONTHS_PER_YEAR);
80888
+ interval_days += input.days;
80889
+ int64_t interval_epoch;
80890
+ interval_epoch = interval_days * Interval::SECS_PER_DAY;
80891
+ // we add 0.25 days per year to sort of account for leap days
80892
+ interval_epoch += interval_years * (Interval::SECS_PER_DAY / 4);
80893
+ interval_epoch += input.micros / Interval::MICROS_PER_SEC;
80894
+ return interval_epoch;
80828
80895
  }
80829
80896
 
80830
80897
  template <>
@@ -86044,36 +86111,7 @@ date_t AddOperator::Operation(int32_t left, date_t right) {
86044
86111
 
86045
86112
  template <>
86046
86113
  date_t AddOperator::Operation(date_t left, interval_t right) {
86047
- date_t result;
86048
- if (right.months != 0) {
86049
- int32_t year, month, day;
86050
- Date::Convert(left, year, month, day);
86051
- int32_t year_diff = right.months / Interval::MONTHS_PER_YEAR;
86052
- year += year_diff;
86053
- month += right.months - year_diff * Interval::MONTHS_PER_YEAR;
86054
- if (month > Interval::MONTHS_PER_YEAR) {
86055
- year++;
86056
- month -= Interval::MONTHS_PER_YEAR;
86057
- } else if (month <= 0) {
86058
- year--;
86059
- month += Interval::MONTHS_PER_YEAR;
86060
- }
86061
- day = MinValue<int32_t>(day, Date::MonthDays(year, month));
86062
- result = Date::FromDate(year, month, day);
86063
- } else {
86064
- result = left;
86065
- }
86066
- if (right.days != 0) {
86067
- if (!TryAddOperator::Operation(result.days, right.days, result.days)) {
86068
- throw OutOfRangeException("Date out of range");
86069
- }
86070
- }
86071
- if (right.micros != 0) {
86072
- if (!TryAddOperator::Operation(result.days, int32_t(right.micros / Interval::MICROS_PER_DAY), result.days)) {
86073
- throw OutOfRangeException("Date out of range");
86074
- }
86075
- }
86076
- return result;
86114
+ return Interval::Add(left, right);
86077
86115
  }
86078
86116
 
86079
86117
  template <>
@@ -86081,26 +86119,13 @@ date_t AddOperator::Operation(interval_t left, date_t right) {
86081
86119
  return AddOperator::Operation<date_t, interval_t, date_t>(right, left);
86082
86120
  }
86083
86121
 
86084
- dtime_t AddIntervalToTimeOperation(dtime_t left, interval_t right, date_t &date) {
86085
- int64_t diff = right.micros - ((right.micros / Interval::MICROS_PER_DAY) * Interval::MICROS_PER_DAY);
86086
- left += diff;
86087
- if (left.micros >= Interval::MICROS_PER_DAY) {
86088
- left.micros -= Interval::MICROS_PER_DAY;
86089
- date.days++;
86090
- } else if (left.micros < 0) {
86091
- left.micros += Interval::MICROS_PER_DAY;
86092
- date.days--;
86093
- }
86094
- return left;
86095
- }
86096
-
86097
86122
  template <>
86098
86123
  timestamp_t AddOperator::Operation(timestamp_t left, interval_t right) {
86099
86124
  date_t date;
86100
86125
  dtime_t time;
86101
86126
  Timestamp::Convert(left, date, time);
86102
- auto new_date = AddOperator::Operation<date_t, interval_t, date_t>(date, right);
86103
- auto new_time = AddIntervalToTimeOperation(time, right, new_date);
86127
+ auto new_date = Interval::Add(date, right);
86128
+ auto new_time = Interval::Add(time, right, new_date);
86104
86129
  return Timestamp::FromDatetime(new_date, new_time);
86105
86130
  }
86106
86131
 
@@ -86233,7 +86258,7 @@ hugeint_t DecimalAddOverflowCheck::Operation(hugeint_t left, hugeint_t right) {
86233
86258
  template <>
86234
86259
  dtime_t AddTimeOperator::Operation(dtime_t left, interval_t right) {
86235
86260
  date_t date(0);
86236
- return AddIntervalToTimeOperation(left, right, date);
86261
+ return Interval::Add(left, right, date);
86237
86262
  }
86238
86263
 
86239
86264
  template <>
@@ -92185,7 +92210,7 @@ string_t SubstringASCII(Vector &result, string_t input, int64_t offset, int64_t
92185
92210
  return SubstringSlice(result, input_data, start, end - start);
92186
92211
  }
92187
92212
 
92188
- string_t SubstringFun::SubstringScalarFunction(Vector &result, string_t input, int32_t offset, int32_t length) {
92213
+ string_t SubstringFun::SubstringScalarFunction(Vector &result, string_t input, int64_t offset, int64_t length) {
92189
92214
  auto input_data = input.GetDataUnsafe();
92190
92215
  auto input_size = input.GetSize();
92191
92216
 
@@ -92252,16 +92277,16 @@ static void SubstringFunction(DataChunk &args, ExpressionState &state, Vector &r
92252
92277
  if (args.ColumnCount() == 3) {
92253
92278
  auto &length_vector = args.data[2];
92254
92279
 
92255
- TernaryExecutor::Execute<string_t, int32_t, int32_t, string_t>(
92280
+ TernaryExecutor::Execute<string_t, int64_t, int64_t, string_t>(
92256
92281
  input_vector, offset_vector, length_vector, result, args.size(),
92257
- [&](string_t input_string, int32_t offset, int32_t length) {
92282
+ [&](string_t input_string, int64_t offset, int64_t length) {
92258
92283
  return SubstringFun::SubstringScalarFunction(result, input_string, offset, length);
92259
92284
  });
92260
92285
  } else {
92261
- BinaryExecutor::Execute<string_t, int32_t, string_t>(
92262
- input_vector, offset_vector, result, args.size(), [&](string_t input_string, int32_t offset) {
92286
+ BinaryExecutor::Execute<string_t, int64_t, string_t>(
92287
+ input_vector, offset_vector, result, args.size(), [&](string_t input_string, int64_t offset) {
92263
92288
  return SubstringFun::SubstringScalarFunction(result, input_string, offset,
92264
- NumericLimits<int32_t>::Maximum());
92289
+ NumericLimits<int64_t>::Maximum() - offset);
92265
92290
  });
92266
92291
  }
92267
92292
  }
@@ -92272,15 +92297,15 @@ static void SubstringFunctionASCII(DataChunk &args, ExpressionState &state, Vect
92272
92297
  if (args.ColumnCount() == 3) {
92273
92298
  auto &length_vector = args.data[2];
92274
92299
 
92275
- TernaryExecutor::Execute<string_t, int32_t, int32_t, string_t>(
92300
+ TernaryExecutor::Execute<string_t, int64_t, int64_t, string_t>(
92276
92301
  input_vector, offset_vector, length_vector, result, args.size(),
92277
- [&](string_t input_string, int32_t offset, int32_t length) {
92302
+ [&](string_t input_string, int64_t offset, int64_t length) {
92278
92303
  return SubstringASCII(result, input_string, offset, length);
92279
92304
  });
92280
92305
  } else {
92281
- BinaryExecutor::Execute<string_t, int32_t, string_t>(
92282
- input_vector, offset_vector, result, args.size(), [&](string_t input_string, int32_t offset) {
92283
- return SubstringASCII(result, input_string, offset, NumericLimits<int32_t>::Maximum());
92306
+ BinaryExecutor::Execute<string_t, int64_t, string_t>(
92307
+ input_vector, offset_vector, result, args.size(), [&](string_t input_string, int64_t offset) {
92308
+ return SubstringASCII(result, input_string, offset, NumericLimits<int64_t>::Maximum() - offset);
92284
92309
  });
92285
92310
  }
92286
92311
  }
@@ -92302,10 +92327,10 @@ static unique_ptr<BaseStatistics> SubstringPropagateStats(ClientContext &context
92302
92327
 
92303
92328
  void SubstringFun::RegisterFunction(BuiltinFunctions &set) {
92304
92329
  ScalarFunctionSet substr("substring");
92305
- substr.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::INTEGER, LogicalType::INTEGER},
92330
+ substr.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::BIGINT, LogicalType::BIGINT},
92306
92331
  LogicalType::VARCHAR, SubstringFunction, false, nullptr, nullptr,
92307
92332
  SubstringPropagateStats));
92308
- substr.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::INTEGER}, LogicalType::VARCHAR,
92333
+ substr.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::BIGINT}, LogicalType::VARCHAR,
92309
92334
  SubstringFunction, false, nullptr, nullptr, SubstringPropagateStats));
92310
92335
  set.AddFunction(substr);
92311
92336
  substr.name = "substr";
@@ -94487,11 +94512,7 @@ static int64_t ParseInteger(vector<Value> &set) {
94487
94512
  //===--------------------------------------------------------------------===//
94488
94513
  static bool ParseBaseOption(BufferedCSVReaderOptions &options, string &loption, vector<Value> &set) {
94489
94514
  if (StringUtil::StartsWith(loption, "delim") || StringUtil::StartsWith(loption, "sep")) {
94490
- options.delimiter = ParseString(set);
94491
- options.has_delimiter = true;
94492
- if (options.delimiter.length() == 0) {
94493
- throw BinderException("DELIM or SEP must not be empty");
94494
- }
94515
+ options.SetDelimiter(ParseString(set));
94495
94516
  } else if (loption == "quote") {
94496
94517
  options.quote = ParseString(set);
94497
94518
  options.has_quote = true;
@@ -95776,8 +95797,7 @@ static unique_ptr<FunctionData> ReadCSVBind(ClientContext &context, vector<Value
95776
95797
  if (kv.first == "auto_detect") {
95777
95798
  options.auto_detect = kv.second.value_.boolean;
95778
95799
  } else if (kv.first == "sep" || kv.first == "delim") {
95779
- options.delimiter = kv.second.str_value;
95780
- options.has_delimiter = true;
95800
+ options.SetDelimiter(kv.second.str_value);
95781
95801
  } else if (kv.first == "header") {
95782
95802
  options.header = kv.second.value_.boolean;
95783
95803
  options.has_header = true;
package/src/duckdb.hpp CHANGED
@@ -10,8 +10,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
10
10
 
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
- #define DUCKDB_SOURCE_ID "770f7d2cc"
14
- #define DUCKDB_VERSION "0.3.2-dev19"
13
+ #define DUCKDB_SOURCE_ID "408ad6407"
14
+ #define DUCKDB_VERSION "0.3.2-dev29"
15
15
  //===----------------------------------------------------------------------===//
16
16
  // DuckDB
17
17
  //
@@ -6014,8 +6014,9 @@ public:
6014
6014
  static constexpr const int32_t MONTHS_PER_YEAR = 12;
6015
6015
  static constexpr const int32_t MONTHS_PER_QUARTER = 3;
6016
6016
  static constexpr const int32_t DAYS_PER_WEEK = 7;
6017
- static constexpr const int64_t DAYS_PER_MONTH =
6018
- 30; // only used for interval comparison/ordering purposes, in which case a month counts as 30 days
6017
+ //! only used for interval comparison/ordering purposes, in which case a month counts as 30 days
6018
+ static constexpr const int64_t DAYS_PER_MONTH = 30;
6019
+ static constexpr const int64_t DAYS_PER_YEAR = 365;
6019
6020
  static constexpr const int64_t MSECS_PER_SEC = 1000;
6020
6021
  static constexpr const int32_t SECS_PER_MINUTE = 60;
6021
6022
  static constexpr const int32_t MINS_PER_HOUR = 60;
@@ -6066,6 +6067,12 @@ public:
6066
6067
  //! Returns the exact difference between two timestamps (days and seconds)
6067
6068
  static interval_t GetDifference(timestamp_t timestamp_1, timestamp_t timestamp_2);
6068
6069
 
6070
+ //! Add an interval to a date
6071
+ static date_t Add(date_t left, interval_t right);
6072
+ //! Add an interval to a time. In case the time overflows or underflows, modify the date by the overflow.
6073
+ //! For example if we go from 23:00 to 02:00, we add a day to the date
6074
+ static dtime_t Add(dtime_t left, interval_t right, date_t &date);
6075
+
6069
6076
  //! Comparison operators
6070
6077
  static bool Equals(interval_t left, interval_t right);
6071
6078
  static bool GreaterThan(interval_t left, interval_t right);