duckdb 0.3.3-dev384.0 → 0.3.3-dev440.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.3-dev384.0",
4
+ "version": "0.3.3-dev440.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -13658,6 +13658,10 @@ bool FileSystem::FileExists(const string &filename) {
13658
13658
  throw NotImplementedException("%s: FileExists is not implemented!", GetName());
13659
13659
  }
13660
13660
 
13661
+ bool FileSystem::IsPipe(const string &filename) {
13662
+ throw NotImplementedException("%s: IsPipe is not implemented!", GetName());
13663
+ }
13664
+
13661
13665
  void FileSystem::RemoveFile(const string &filename) {
13662
13666
  throw NotImplementedException("%s: RemoveFile is not implemented!", GetName());
13663
13667
  }
@@ -15773,6 +15777,9 @@ public:
15773
15777
  void MoveFile(const string &source, const string &target) override;
15774
15778
  //! Check if a file exists
15775
15779
  bool FileExists(const string &filename) override;
15780
+
15781
+ //! Check if path is a pipe
15782
+ bool IsPipe(const string &filename) override;
15776
15783
  //! Remove a file from disk
15777
15784
  void RemoveFile(const string &filename) override;
15778
15785
  //! Sync a file handle to disk
@@ -15865,8 +15872,10 @@ public:
15865
15872
  } // namespace duckdb
15866
15873
 
15867
15874
  #include <string>
15875
+ #include <io.h>
15868
15876
 
15869
15877
  #ifdef __MINGW32__
15878
+ #include <sys/stat.h>
15870
15879
  // need to manually define this for mingw
15871
15880
  extern "C" WINBASEAPI BOOL WINAPI GetPhysicallyInstalledSystemMemory(PULONGLONG);
15872
15881
  #endif
@@ -15891,6 +15900,90 @@ static void AssertValidFileFlags(uint8_t flags) {
15891
15900
  #endif
15892
15901
  }
15893
15902
 
15903
+ #ifdef __MINGW32__
15904
+ bool LocalFileSystem::FileExists(const string &filename) {
15905
+ auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str());
15906
+ const wchar_t *wpath = unicode_path.c_str();
15907
+ if (_waccess(wpath, 0) == 0) {
15908
+ struct _stat64i32 status;
15909
+ _wstat(wpath, &status);
15910
+ if (status.st_size > 0) {
15911
+ return true;
15912
+ }
15913
+ }
15914
+ return false;
15915
+ }
15916
+ bool LocalFileSystem::IsPipe(const string &filename) {
15917
+ auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str());
15918
+ const wchar_t *wpath = unicode_path.c_str();
15919
+ if (_waccess(wpath, 0) == 0) {
15920
+ struct _stat64i32 status;
15921
+ _wstat(wpath, &status);
15922
+ if (status.st_size == 0) {
15923
+ return true;
15924
+ }
15925
+ }
15926
+ return false;
15927
+ }
15928
+
15929
+ #else
15930
+ #ifndef _WIN32
15931
+ bool LocalFileSystem::FileExists(const string &filename) {
15932
+ if (!filename.empty()) {
15933
+ if (access(filename.c_str(), 0) == 0) {
15934
+ struct stat status;
15935
+ stat(filename.c_str(), &status);
15936
+ if (S_ISREG(status.st_mode)) {
15937
+ return true;
15938
+ }
15939
+ }
15940
+ }
15941
+ // if any condition fails
15942
+ return false;
15943
+ }
15944
+
15945
+ bool LocalFileSystem::IsPipe(const string &filename) {
15946
+ if (!filename.empty()) {
15947
+ if (access(filename.c_str(), 0) == 0) {
15948
+ struct stat status;
15949
+ stat(filename.c_str(), &status);
15950
+ if (S_ISFIFO(status.st_mode)) {
15951
+ return true;
15952
+ }
15953
+ }
15954
+ }
15955
+ // if any condition fails
15956
+ return false;
15957
+ }
15958
+
15959
+ #else
15960
+ bool LocalFileSystem::FileExists(const string &filename) {
15961
+ auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str());
15962
+ const wchar_t *wpath = unicode_path.c_str();
15963
+ if (_waccess(wpath, 0) == 0) {
15964
+ struct _stat64i32 status;
15965
+ _wstat(wpath, &status);
15966
+ if (status.st_mode & S_IFREG) {
15967
+ return true;
15968
+ }
15969
+ }
15970
+ return false;
15971
+ }
15972
+ bool LocalFileSystem::IsPipe(const string &filename) {
15973
+ auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str());
15974
+ const wchar_t *wpath = unicode_path.c_str();
15975
+ if (_waccess(wpath, 0) == 0) {
15976
+ struct _stat64i32 status;
15977
+ _wstat(wpath, &status);
15978
+ if (status.st_mode & _S_IFCHR) {
15979
+ return true;
15980
+ }
15981
+ }
15982
+ return false;
15983
+ }
15984
+ #endif
15985
+ #endif
15986
+
15894
15987
  #ifndef _WIN32
15895
15988
  // somehow sometimes this is missing
15896
15989
  #ifndef O_CLOEXEC
@@ -16127,20 +16220,6 @@ bool LocalFileSystem::DirectoryExists(const string &directory) {
16127
16220
  return false;
16128
16221
  }
16129
16222
 
16130
- bool LocalFileSystem::FileExists(const string &filename) {
16131
- if (!filename.empty()) {
16132
- if (access(filename.c_str(), 0) == 0) {
16133
- struct stat status;
16134
- stat(filename.c_str(), &status);
16135
- if (!(status.st_mode & S_IFDIR)) {
16136
- return true;
16137
- }
16138
- }
16139
- }
16140
- // if any condition fails
16141
- return false;
16142
- }
16143
-
16144
16223
  void LocalFileSystem::CreateDirectory(const string &directory) {
16145
16224
  struct stat st;
16146
16225
 
@@ -16479,11 +16558,6 @@ bool LocalFileSystem::DirectoryExists(const string &directory) {
16479
16558
  return (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY));
16480
16559
  }
16481
16560
 
16482
- bool LocalFileSystem::FileExists(const string &filename) {
16483
- DWORD attrs = WindowsGetFileAttributes(filename);
16484
- return (attrs != INVALID_FILE_ATTRIBUTES && !(attrs & FILE_ATTRIBUTE_DIRECTORY));
16485
- }
16486
-
16487
16561
  void LocalFileSystem::CreateDirectory(const string &directory) {
16488
16562
  if (DirectoryExists(directory)) {
16489
16563
  return;
@@ -16642,9 +16716,9 @@ vector<string> LocalFileSystem::Glob(const string &path) {
16642
16716
  }
16643
16717
  // first check if the path has a glob at all
16644
16718
  if (!HasGlob(path)) {
16645
- // no glob: return only the file (if it exists)
16719
+ // no glob: return only the file (if it exists or is a pipe)
16646
16720
  vector<string> result;
16647
- if (FileExists(path)) {
16721
+ if (FileExists(path) || IsPipe(path)) {
16648
16722
  result.push_back(path);
16649
16723
  }
16650
16724
  return result;
@@ -45465,6 +45539,9 @@ public:
45465
45539
  return FindFileSystem(filename)->FileExists(filename);
45466
45540
  }
45467
45541
 
45542
+ bool IsPipe(const string &filename) override {
45543
+ return FindFileSystem(filename)->IsPipe(filename);
45544
+ }
45468
45545
  virtual void RemoveFile(const string &filename) override {
45469
45546
  FindFileSystem(filename)->RemoveFile(filename);
45470
45547
  }
@@ -61229,6 +61306,8 @@ public:
61229
61306
 
61230
61307
  CopyFunction function;
61231
61308
  unique_ptr<FunctionData> bind_data;
61309
+ string file_path;
61310
+ bool use_tmp_file;
61232
61311
 
61233
61312
  public:
61234
61313
  // Source interface
@@ -61254,6 +61333,7 @@ public:
61254
61333
 
61255
61334
 
61256
61335
 
61336
+
61257
61337
  #include <algorithm>
61258
61338
 
61259
61339
  namespace duckdb {
@@ -61278,6 +61358,15 @@ public:
61278
61358
  //===--------------------------------------------------------------------===//
61279
61359
  // Sink
61280
61360
  //===--------------------------------------------------------------------===//
61361
+ void MoveTmpFile(ClientContext &context, const string &tmp_file_path) {
61362
+ auto &fs = FileSystem::GetFileSystem(context);
61363
+ auto file_path = tmp_file_path.substr(0, tmp_file_path.length() - 4);
61364
+ if (fs.FileExists(file_path)) {
61365
+ fs.RemoveFile(file_path);
61366
+ }
61367
+ fs.MoveFile(tmp_file_path, file_path);
61368
+ }
61369
+
61281
61370
  PhysicalCopyToFile::PhysicalCopyToFile(vector<LogicalType> types, CopyFunction function_p,
61282
61371
  unique_ptr<FunctionData> bind_data, idx_t estimated_cardinality)
61283
61372
  : PhysicalOperator(PhysicalOperatorType::COPY_TO_FILE, move(types), estimated_cardinality),
@@ -61308,6 +61397,10 @@ SinkFinalizeType PhysicalCopyToFile::Finalize(Pipeline &pipeline, Event &event,
61308
61397
  auto &gstate = (CopyToFunctionGlobalState &)gstate_p;
61309
61398
  if (function.copy_to_finalize) {
61310
61399
  function.copy_to_finalize(context, *bind_data, *gstate.global_state);
61400
+
61401
+ if (use_tmp_file) {
61402
+ MoveTmpFile(context, file_path);
61403
+ }
61311
61404
  }
61312
61405
  return SinkFinalizeType::READY;
61313
61406
  }
@@ -61316,7 +61409,7 @@ unique_ptr<LocalSinkState> PhysicalCopyToFile::GetLocalSinkState(ExecutionContex
61316
61409
  return make_unique<CopyToFunctionLocalState>(function.copy_to_initialize_local(context.client, *bind_data));
61317
61410
  }
61318
61411
  unique_ptr<GlobalSinkState> PhysicalCopyToFile::GetGlobalSinkState(ClientContext &context) const {
61319
- return make_unique<CopyToFunctionGlobalState>(function.copy_to_initialize_global(context, *bind_data));
61412
+ return make_unique<CopyToFunctionGlobalState>(function.copy_to_initialize_global(context, *bind_data, file_path));
61320
61413
  }
61321
61414
 
61322
61415
  //===--------------------------------------------------------------------===//
@@ -65351,6 +65444,7 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalComparison
65351
65444
 
65352
65445
 
65353
65446
 
65447
+
65354
65448
  namespace duckdb {
65355
65449
 
65356
65450
  class LogicalCopyToFile : public LogicalOperator {
@@ -65360,6 +65454,9 @@ public:
65360
65454
  }
65361
65455
  CopyFunction function;
65362
65456
  unique_ptr<FunctionData> bind_data;
65457
+ std::string file_path;
65458
+ bool use_tmp_file;
65459
+ bool is_file_and_exists;
65363
65460
 
65364
65461
  protected:
65365
65462
  void ResolveTypes() override {
@@ -65373,8 +65470,14 @@ namespace duckdb {
65373
65470
 
65374
65471
  unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalCopyToFile &op) {
65375
65472
  auto plan = CreatePlan(*op.children[0]);
65473
+ bool use_tmp_file = op.is_file_and_exists && op.use_tmp_file;
65474
+ if (use_tmp_file) {
65475
+ op.file_path += ".tmp";
65476
+ }
65376
65477
  // COPY from select statement to file
65377
65478
  auto copy = make_unique<PhysicalCopyToFile>(op.types, op.function, move(op.bind_data), op.estimated_cardinality);
65479
+ copy->file_path = op.file_path;
65480
+ copy->use_tmp_file = use_tmp_file;
65378
65481
 
65379
65482
  copy->children.push_back(move(plan));
65380
65483
  return move(copy);
@@ -95093,10 +95196,11 @@ static unique_ptr<LocalFunctionData> WriteCSVInitializeLocal(ClientContext &cont
95093
95196
  return move(local_data);
95094
95197
  }
95095
95198
 
95096
- static unique_ptr<GlobalFunctionData> WriteCSVInitializeGlobal(ClientContext &context, FunctionData &bind_data) {
95199
+ static unique_ptr<GlobalFunctionData> WriteCSVInitializeGlobal(ClientContext &context, FunctionData &bind_data,
95200
+ const string &file_path) {
95097
95201
  auto &csv_data = (WriteCSVData &)bind_data;
95098
95202
  auto &options = csv_data.options;
95099
- auto global_data = make_unique<GlobalWriteCSVData>(FileSystem::GetFileSystem(context), csv_data.files[0],
95203
+ auto global_data = make_unique<GlobalWriteCSVData>(FileSystem::GetFileSystem(context), file_path,
95100
95204
  FileSystem::GetFileOpener(context), options.compression);
95101
95205
 
95102
95206
  if (options.header) {
@@ -95190,6 +95294,7 @@ static void WriteCSVCombine(ClientContext &context, FunctionData &bind_data, Glo
95190
95294
  //===--------------------------------------------------------------------===//
95191
95295
  void WriteCSVFinalize(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate) {
95192
95296
  auto &global_state = (GlobalWriteCSVData &)gstate;
95297
+
95193
95298
  global_state.handle->Close();
95194
95299
  global_state.handle.reset();
95195
95300
  }
@@ -100231,6 +100336,7 @@ void BaseAppender::Close() {
100231
100336
 
100232
100337
 
100233
100338
 
100339
+
100234
100340
  #include <cstring>
100235
100341
  #include <cassert>
100236
100342
 
@@ -100265,6 +100371,10 @@ duckdb_type ConvertCPPTypeToC(const LogicalType &type);
100265
100371
  idx_t GetCTypeSize(duckdb_type type);
100266
100372
  duckdb_state duckdb_translate_result(MaterializedQueryResult *result, duckdb_result *out);
100267
100373
 
100374
+ struct DuckDBColumnData {
100375
+ LogicalType type;
100376
+ };
100377
+
100268
100378
  } // namespace duckdb
100269
100379
 
100270
100380
 
@@ -100810,6 +100920,8 @@ duckdb_type ConvertCPPTypeToC(const LogicalType &sql_type) {
100810
100920
  return DUCKDB_TYPE_BLOB;
100811
100921
  case LogicalTypeId::INTERVAL:
100812
100922
  return DUCKDB_TYPE_INTERVAL;
100923
+ case LogicalTypeId::DECIMAL:
100924
+ return DUCKDB_TYPE_DECIMAL;
100813
100925
  default: // LCOV_EXCL_START
100814
100926
  D_ASSERT(0);
100815
100927
  return DUCKDB_TYPE_INVALID;
@@ -100853,6 +100965,8 @@ idx_t GetCTypeSize(duckdb_type type) {
100853
100965
  return sizeof(duckdb_blob);
100854
100966
  case DUCKDB_TYPE_INTERVAL:
100855
100967
  return sizeof(duckdb_interval);
100968
+ case DUCKDB_TYPE_DECIMAL:
100969
+ return sizeof(duckdb_hugeint);
100856
100970
  default: // LCOV_EXCL_START
100857
100971
  // unsupported type
100858
100972
  D_ASSERT(0);
@@ -100872,6 +100986,8 @@ void duckdb_free(void *ptr) {
100872
100986
 
100873
100987
 
100874
100988
 
100989
+
100990
+
100875
100991
  using duckdb::Hugeint;
100876
100992
  using duckdb::hugeint_t;
100877
100993
  using duckdb::Value;
@@ -100896,6 +101012,15 @@ duckdb_hugeint duckdb_double_to_hugeint(double val) {
100896
101012
  return result;
100897
101013
  }
100898
101014
 
101015
+ double duckdb_decimal_to_double(duckdb_decimal val) {
101016
+ double result;
101017
+ hugeint_t value;
101018
+ value.lower = val.value.lower;
101019
+ value.upper = val.value.upper;
101020
+ duckdb::TryCastFromDecimal::Operation<hugeint_t, double>(value, result, nullptr, val.width, val.scale);
101021
+ return result;
101022
+ }
101023
+
100899
101024
 
100900
101025
 
100901
101026
 
@@ -101133,6 +101258,9 @@ duckdb_state duckdb_translate_result(MaterializedQueryResult *result, duckdb_res
101133
101258
  // zero initialize the columns (so we can cleanly delete it in case a malloc fails)
101134
101259
  memset(out->__deprecated_columns, 0, sizeof(duckdb_column) * out->__deprecated_column_count);
101135
101260
  for (idx_t i = 0; i < out->__deprecated_column_count; i++) {
101261
+ auto column_data = new DuckDBColumnData();
101262
+ column_data->type = result->types[i];
101263
+ out->__deprecated_columns[i].internal_data = column_data;
101136
101264
  out->__deprecated_columns[i].__deprecated_type = ConvertCPPTypeToC(result->types[i]);
101137
101265
  out->__deprecated_columns[i].__deprecated_name = strdup(result->names[i].c_str());
101138
101266
  out->__deprecated_columns[i].__deprecated_nullmask =
@@ -101295,9 +101423,72 @@ duckdb_state duckdb_translate_result(MaterializedQueryResult *result, duckdb_res
101295
101423
  }
101296
101424
  break;
101297
101425
  }
101426
+ case LogicalTypeId::DECIMAL: {
101427
+ // get data
101428
+ idx_t row = 0;
101429
+ auto target = (hugeint_t *)out->__deprecated_columns[col].__deprecated_data;
101430
+ switch (result->types[col].InternalType()) {
101431
+ case PhysicalType::INT16: {
101432
+ for (auto &chunk : result->collection.Chunks()) {
101433
+ auto source = FlatVector::GetData<int16_t>(chunk->data[col]);
101434
+ for (idx_t k = 0; k < chunk->size(); k++) {
101435
+ if (!FlatVector::IsNull(chunk->data[col], k)) {
101436
+ target[row].lower = source[k];
101437
+ target[row].upper = 0;
101438
+ }
101439
+ row++;
101440
+ }
101441
+ }
101442
+ break;
101443
+ }
101444
+ case PhysicalType::INT32: {
101445
+ for (auto &chunk : result->collection.Chunks()) {
101446
+ auto source = FlatVector::GetData<int32_t>(chunk->data[col]);
101447
+ for (idx_t k = 0; k < chunk->size(); k++) {
101448
+ if (!FlatVector::IsNull(chunk->data[col], k)) {
101449
+ target[row].lower = source[k];
101450
+ target[row].upper = 0;
101451
+ }
101452
+ row++;
101453
+ }
101454
+ }
101455
+ break;
101456
+ }
101457
+ case PhysicalType::INT64: {
101458
+ for (auto &chunk : result->collection.Chunks()) {
101459
+ auto source = FlatVector::GetData<int64_t>(chunk->data[col]);
101460
+ for (idx_t k = 0; k < chunk->size(); k++) {
101461
+ if (!FlatVector::IsNull(chunk->data[col], k)) {
101462
+ target[row].lower = source[k];
101463
+ target[row].upper = 0;
101464
+ }
101465
+ row++;
101466
+ }
101467
+ }
101468
+ break;
101469
+ }
101470
+ case PhysicalType::INT128: {
101471
+ for (auto &chunk : result->collection.Chunks()) {
101472
+ auto source = FlatVector::GetData<hugeint_t>(chunk->data[col]);
101473
+ for (idx_t k = 0; k < chunk->size(); k++) {
101474
+ if (!FlatVector::IsNull(chunk->data[col], k)) {
101475
+ target[row].lower = source[k].lower;
101476
+ target[row].upper = source[k].upper;
101477
+ }
101478
+ row++;
101479
+ }
101480
+ }
101481
+ break;
101482
+ }
101483
+ default:
101484
+ throw std::runtime_error("Unsupported physical type for Decimal" +
101485
+ TypeIdToString(result->types[col].InternalType()));
101486
+ }
101487
+ break;
101488
+ }
101298
101489
  default: // LCOV_EXCL_START
101299
- // unsupported type for C API
101300
- D_ASSERT(0);
101490
+ std::string err_msg = "Unsupported type for C API: " + result->types[col].ToString();
101491
+ out->__deprecated_error_message = strdup(err_msg.c_str());
101301
101492
  return DuckDBError;
101302
101493
  } // LCOV_EXCL_STOP
101303
101494
  }
@@ -101333,6 +101524,10 @@ static void DuckdbDestroyColumn(duckdb_column column, idx_t count) {
101333
101524
  if (column.__deprecated_name) {
101334
101525
  duckdb_free(column.__deprecated_name);
101335
101526
  }
101527
+ if (column.internal_data) {
101528
+ auto column_data = (duckdb::DuckDBColumnData *)column.internal_data;
101529
+ delete column_data;
101530
+ }
101336
101531
  }
101337
101532
 
101338
101533
  void duckdb_destroy_result(duckdb_result *result) {
@@ -101547,7 +101742,12 @@ using duckdb::UnsafeFetch;
101547
101742
  template <class SOURCE_TYPE, class RESULT_TYPE, class OP>
101548
101743
  RESULT_TYPE TryCastCInternal(duckdb_result *result, idx_t col, idx_t row) {
101549
101744
  RESULT_TYPE result_value;
101550
- if (!OP::template Operation<SOURCE_TYPE, RESULT_TYPE>(UnsafeFetch<SOURCE_TYPE>(result, col, row), result_value)) {
101745
+ try {
101746
+ if (!OP::template Operation<SOURCE_TYPE, RESULT_TYPE>(UnsafeFetch<SOURCE_TYPE>(result, col, row),
101747
+ result_value)) {
101748
+ return FetchDefaultValue::Operation<RESULT_TYPE>();
101749
+ }
101750
+ } catch (...) {
101551
101751
  return FetchDefaultValue::Operation<RESULT_TYPE>();
101552
101752
  }
101553
101753
  return result_value;
@@ -101599,6 +101799,8 @@ static RESULT_TYPE GetInternalCValue(duckdb_result *result, idx_t col, idx_t row
101599
101799
  return TryCastCInternal<timestamp_t, RESULT_TYPE, OP>(result, col, row);
101600
101800
  case DUCKDB_TYPE_HUGEINT:
101601
101801
  return TryCastCInternal<hugeint_t, RESULT_TYPE, OP>(result, col, row);
101802
+ case DUCKDB_TYPE_DECIMAL:
101803
+ return TryCastCInternal<hugeint_t, RESULT_TYPE, OP>(result, col, row);
101602
101804
  case DUCKDB_TYPE_INTERVAL:
101603
101805
  return TryCastCInternal<interval_t, RESULT_TYPE, OP>(result, col, row);
101604
101806
  case DUCKDB_TYPE_VARCHAR:
@@ -101635,6 +101837,18 @@ int64_t duckdb_value_int64(duckdb_result *result, idx_t col, idx_t row) {
101635
101837
  return GetInternalCValue<int64_t>(result, col, row);
101636
101838
  }
101637
101839
 
101840
+ duckdb_decimal duckdb_value_decimal(duckdb_result *result, idx_t col, idx_t row) {
101841
+ duckdb_decimal result_value;
101842
+
101843
+ auto column_data = (duckdb::DuckDBColumnData *)result->__deprecated_columns[col].internal_data;
101844
+ column_data->type.GetDecimalProperties(result_value.width, result_value.scale);
101845
+
101846
+ auto internal_value = GetInternalCValue<hugeint_t>(result, col, row);
101847
+ result_value.value.lower = internal_value.lower;
101848
+ result_value.value.upper = internal_value.upper;
101849
+ return result_value;
101850
+ }
101851
+
101638
101852
  duckdb_hugeint duckdb_value_hugeint(duckdb_result *result, idx_t col, idx_t row) {
101639
101853
  duckdb_hugeint result_value;
101640
101854
  auto internal_value = GetInternalCValue<hugeint_t>(result, col, row);
@@ -101728,6 +101942,7 @@ bool duckdb_value_is_null(duckdb_result *result, idx_t col, idx_t row) {
101728
101942
  return result->__deprecated_columns[col].__deprecated_nullmask[row];
101729
101943
  }
101730
101944
 
101945
+
101731
101946
  //===----------------------------------------------------------------------===//
101732
101947
  // DuckDB
101733
101948
  //
@@ -114098,6 +114313,9 @@ bool QueryResult::Equals(QueryResult &other) { // LCOV_EXCL_START
114098
114313
  for (idx_t row = 0; row < rchunk->size(); row++) {
114099
114314
  auto lvalue = lchunk->GetValue(col, row);
114100
114315
  auto rvalue = rchunk->GetValue(col, row);
114316
+ if (lvalue.IsNull() && rvalue.IsNull()) {
114317
+ continue;
114318
+ }
114101
114319
  if (lvalue != rvalue) {
114102
114320
  return false;
114103
114321
  }
@@ -115597,7 +115815,7 @@ string ProjectionRelation::ToString(idx_t depth) {
115597
115815
  if (i != 0) {
115598
115816
  str += ", ";
115599
115817
  }
115600
- str += expressions[i]->ToString();
115818
+ str += expressions[i]->ToString() + " as " + expressions[i]->alias;
115601
115819
  }
115602
115820
  str += "]\n";
115603
115821
  return str + child->ToString(depth + 1);
@@ -150267,6 +150485,8 @@ BoundStatement Binder::Bind(CallStatement &stmt) {
150267
150485
 
150268
150486
 
150269
150487
 
150488
+
150489
+
150270
150490
  #include <algorithm>
150271
150491
 
150272
150492
  namespace duckdb {
@@ -150290,11 +150510,24 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) {
150290
150510
  if (!copy_function->function.copy_to_bind) {
150291
150511
  throw NotImplementedException("COPY TO is not supported for FORMAT \"%s\"", stmt.info->format);
150292
150512
  }
150293
-
150513
+ bool use_tmp_file = true;
150514
+ for (auto &option : stmt.info->options) {
150515
+ auto loption = StringUtil::Lower(option.first);
150516
+ if (loption == "use_tmp_file") {
150517
+ use_tmp_file = option.second[0].CastAs(LogicalType::BOOLEAN).GetValue<bool>();
150518
+ stmt.info->options.erase(option.first);
150519
+ break;
150520
+ }
150521
+ }
150294
150522
  auto function_data =
150295
150523
  copy_function->function.copy_to_bind(context, *stmt.info, select_node.names, select_node.types);
150296
150524
  // now create the copy information
150297
150525
  auto copy = make_unique<LogicalCopyToFile>(copy_function->function, move(function_data));
150526
+ copy->file_path = stmt.info->file_path;
150527
+ copy->use_tmp_file = use_tmp_file;
150528
+ LocalFileSystem fs;
150529
+ copy->is_file_and_exists = fs.FileExists(copy->file_path);
150530
+
150298
150531
  copy->AddChild(move(select_node.plan));
150299
150532
 
150300
150533
  result.plan = move(copy);
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 "f95a319a9"
15
- #define DUCKDB_VERSION "v0.3.3-dev384"
14
+ #define DUCKDB_SOURCE_ID "f7a783d93"
15
+ #define DUCKDB_VERSION "v0.3.3-dev440"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -1930,11 +1930,12 @@ public:
1930
1930
  DUCKDB_API virtual void MoveFile(const string &source, const string &target);
1931
1931
  //! Check if a file exists
1932
1932
  DUCKDB_API virtual bool FileExists(const string &filename);
1933
+ //! Check if path is pipe
1934
+ DUCKDB_API virtual bool IsPipe(const string &filename);
1933
1935
  //! Remove a file from disk
1934
1936
  DUCKDB_API virtual void RemoveFile(const string &filename);
1935
1937
  //! Sync a file handle to disk
1936
1938
  DUCKDB_API virtual void FileSync(FileHandle &handle);
1937
-
1938
1939
  //! Sets the working directory
1939
1940
  DUCKDB_API static void SetWorkingDirectory(const string &path);
1940
1941
  //! Gets the working directory
@@ -8710,7 +8711,7 @@ public:
8710
8711
  virtual string GetName() const;
8711
8712
  virtual string ParamsToString() const;
8712
8713
  virtual string ToString() const;
8713
- void Print();
8714
+ DUCKDB_API void Print();
8714
8715
  //! Debug method: verify that the integrity of expressions & child nodes are maintained
8715
8716
  virtual void Verify();
8716
8717
 
@@ -12069,7 +12070,9 @@ typedef enum DUCKDB_TYPE {
12069
12070
  // const char*
12070
12071
  DUCKDB_TYPE_VARCHAR,
12071
12072
  // duckdb_blob
12072
- DUCKDB_TYPE_BLOB
12073
+ DUCKDB_TYPE_BLOB,
12074
+ // decimal
12075
+ DUCKDB_TYPE_DECIMAL
12073
12076
  } duckdb_type;
12074
12077
 
12075
12078
  //! Days are stored as days since 1970-01-01
@@ -12122,6 +12125,13 @@ typedef struct {
12122
12125
  int64_t upper;
12123
12126
  } duckdb_hugeint;
12124
12127
 
12128
+ typedef struct {
12129
+ uint8_t width;
12130
+ uint8_t scale;
12131
+
12132
+ duckdb_hugeint value;
12133
+ } duckdb_decimal;
12134
+
12125
12135
  typedef struct {
12126
12136
  void *data;
12127
12137
  idx_t size;
@@ -12456,6 +12466,11 @@ DUCKDB_API int64_t duckdb_value_int64(duckdb_result *result, idx_t col, idx_t ro
12456
12466
  */
12457
12467
  DUCKDB_API duckdb_hugeint duckdb_value_hugeint(duckdb_result *result, idx_t col, idx_t row);
12458
12468
 
12469
+ /*!
12470
+ * returns: The duckdb_decimal value at the specified location, or 0 if the value cannot be converted.
12471
+ */
12472
+ DUCKDB_API duckdb_decimal duckdb_value_decimal(duckdb_result *result, idx_t col, idx_t row);
12473
+
12459
12474
  /*!
12460
12475
  * returns: The uint8_t value at the specified location, or 0 if the value cannot be converted.
12461
12476
  */
@@ -12622,6 +12637,17 @@ If the conversion fails because the double value is too big the result will be 0
12622
12637
  */
12623
12638
  DUCKDB_API duckdb_hugeint duckdb_double_to_hugeint(double val);
12624
12639
 
12640
+ //===--------------------------------------------------------------------===//
12641
+ // Decimal Helpers
12642
+ //===--------------------------------------------------------------------===//
12643
+ /*!
12644
+ Converts a duckdb_decimal object (as obtained from a `DUCKDB_TYPE_DECIMAL` column) into a double.
12645
+
12646
+ * val: The decimal value.
12647
+ * returns: The converted `double` element.
12648
+ */
12649
+ DUCKDB_API double duckdb_decimal_to_double(duckdb_decimal val);
12650
+
12625
12651
  //===--------------------------------------------------------------------===//
12626
12652
  // Prepared Statements
12627
12653
  //===--------------------------------------------------------------------===//
@@ -18076,7 +18102,8 @@ struct GlobalFunctionData {
18076
18102
  typedef unique_ptr<FunctionData> (*copy_to_bind_t)(ClientContext &context, CopyInfo &info, vector<string> &names,
18077
18103
  vector<LogicalType> &sql_types);
18078
18104
  typedef unique_ptr<LocalFunctionData> (*copy_to_initialize_local_t)(ClientContext &context, FunctionData &bind_data);
18079
- typedef unique_ptr<GlobalFunctionData> (*copy_to_initialize_global_t)(ClientContext &context, FunctionData &bind_data);
18105
+ typedef unique_ptr<GlobalFunctionData> (*copy_to_initialize_global_t)(ClientContext &context, FunctionData &bind_data,
18106
+ const string &file_path);
18080
18107
  typedef void (*copy_to_sink_t)(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate,
18081
18108
  LocalFunctionData &lstate, DataChunk &input);
18082
18109
  typedef void (*copy_to_combine_t)(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate,