duckdb 0.3.2-dev838.0 → 0.3.2-dev856.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.cpp +628 -17
- package/src/duckdb.hpp +8 -6
- package/src/parquet-amalgamation.cpp +36557 -36552
package/src/duckdb.cpp
CHANGED
|
@@ -21139,12 +21139,14 @@ public:
|
|
|
21139
21139
|
|
|
21140
21140
|
int64_t GetFileSize(FileHandle &handle) override;
|
|
21141
21141
|
|
|
21142
|
+
void Reset(FileHandle &handle) override;
|
|
21142
21143
|
bool OnDiskFile(FileHandle &handle) override {
|
|
21143
21144
|
return false;
|
|
21144
21145
|
};
|
|
21145
21146
|
bool CanSeek() override {
|
|
21146
21147
|
return false;
|
|
21147
21148
|
}
|
|
21149
|
+
void FileSync(FileHandle &handle) override;
|
|
21148
21150
|
|
|
21149
21151
|
std::string GetName() const override {
|
|
21150
21152
|
return "PipeFileSystem";
|
|
@@ -21181,6 +21183,10 @@ int64_t PipeFile::WriteChunk(void *buffer, int64_t nr_bytes) {
|
|
|
21181
21183
|
return child_handle->Write(buffer, nr_bytes);
|
|
21182
21184
|
}
|
|
21183
21185
|
|
|
21186
|
+
void PipeFileSystem::Reset(FileHandle &handle) {
|
|
21187
|
+
throw InternalException("Cannot reset pipe file system");
|
|
21188
|
+
}
|
|
21189
|
+
|
|
21184
21190
|
int64_t PipeFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes) {
|
|
21185
21191
|
auto &pipe = (PipeFile &)handle;
|
|
21186
21192
|
return pipe.ReadChunk(buffer, nr_bytes);
|
|
@@ -21195,6 +21201,9 @@ int64_t PipeFileSystem::GetFileSize(FileHandle &handle) {
|
|
|
21195
21201
|
return 0;
|
|
21196
21202
|
}
|
|
21197
21203
|
|
|
21204
|
+
void PipeFileSystem::FileSync(FileHandle &handle) {
|
|
21205
|
+
}
|
|
21206
|
+
|
|
21198
21207
|
unique_ptr<FileHandle> PipeFileSystem::OpenPipe(unique_ptr<FileHandle> handle) {
|
|
21199
21208
|
auto path = handle->path;
|
|
21200
21209
|
return make_unique<PipeFile>(move(handle), path);
|
|
@@ -56617,6 +56626,125 @@ string PhysicalTopN::ParamsToString() const {
|
|
|
56617
56626
|
|
|
56618
56627
|
namespace duckdb {
|
|
56619
56628
|
|
|
56629
|
+
struct CSVFileHandle {
|
|
56630
|
+
public:
|
|
56631
|
+
explicit CSVFileHandle(unique_ptr<FileHandle> file_handle_p) : file_handle(move(file_handle_p)) {
|
|
56632
|
+
can_seek = file_handle->CanSeek();
|
|
56633
|
+
plain_file_source = file_handle->OnDiskFile() && can_seek;
|
|
56634
|
+
file_size = file_handle->GetFileSize();
|
|
56635
|
+
}
|
|
56636
|
+
|
|
56637
|
+
bool CanSeek() {
|
|
56638
|
+
return can_seek;
|
|
56639
|
+
}
|
|
56640
|
+
void Seek(idx_t position) {
|
|
56641
|
+
if (!can_seek) {
|
|
56642
|
+
throw InternalException("Cannot seek in this file");
|
|
56643
|
+
}
|
|
56644
|
+
file_handle->Seek(position);
|
|
56645
|
+
}
|
|
56646
|
+
idx_t SeekPosition() {
|
|
56647
|
+
if (!can_seek) {
|
|
56648
|
+
throw InternalException("Cannot seek in this file");
|
|
56649
|
+
}
|
|
56650
|
+
return file_handle->SeekPosition();
|
|
56651
|
+
}
|
|
56652
|
+
void Reset() {
|
|
56653
|
+
if (plain_file_source) {
|
|
56654
|
+
file_handle->Reset();
|
|
56655
|
+
} else {
|
|
56656
|
+
if (!reset_enabled) {
|
|
56657
|
+
throw InternalException("Reset called but reset is not enabled for this CSV Handle");
|
|
56658
|
+
}
|
|
56659
|
+
read_position = 0;
|
|
56660
|
+
}
|
|
56661
|
+
}
|
|
56662
|
+
bool PlainFileSource() {
|
|
56663
|
+
return plain_file_source;
|
|
56664
|
+
}
|
|
56665
|
+
|
|
56666
|
+
idx_t FileSize() {
|
|
56667
|
+
return file_size;
|
|
56668
|
+
}
|
|
56669
|
+
|
|
56670
|
+
idx_t Read(void *buffer, idx_t nr_bytes) {
|
|
56671
|
+
if (!plain_file_source) {
|
|
56672
|
+
// not a plain file source: we need to do some bookkeeping around the reset functionality
|
|
56673
|
+
idx_t result_offset = 0;
|
|
56674
|
+
if (read_position < buffer_size) {
|
|
56675
|
+
// we need to read from our cached buffer
|
|
56676
|
+
auto buffer_read_count = MinValue<idx_t>(nr_bytes, buffer_size - read_position);
|
|
56677
|
+
memcpy(buffer, cached_buffer.get() + read_position, buffer_read_count);
|
|
56678
|
+
result_offset += buffer_read_count;
|
|
56679
|
+
read_position += buffer_read_count;
|
|
56680
|
+
if (result_offset == nr_bytes) {
|
|
56681
|
+
return nr_bytes;
|
|
56682
|
+
}
|
|
56683
|
+
} else if (!reset_enabled && cached_buffer) {
|
|
56684
|
+
// reset is disabled but we still have cached data
|
|
56685
|
+
// we can remove any cached data
|
|
56686
|
+
cached_buffer.reset();
|
|
56687
|
+
buffer_size = 0;
|
|
56688
|
+
buffer_capacity = 0;
|
|
56689
|
+
read_position = 0;
|
|
56690
|
+
}
|
|
56691
|
+
// we have data left to read from the file
|
|
56692
|
+
// read directly into the buffer
|
|
56693
|
+
auto bytes_read = file_handle->Read((char *)buffer + result_offset, nr_bytes - result_offset);
|
|
56694
|
+
read_position += bytes_read;
|
|
56695
|
+
if (reset_enabled) {
|
|
56696
|
+
// if reset caching is enabled, we need to cache the bytes that we have read
|
|
56697
|
+
if (buffer_size + bytes_read >= buffer_capacity) {
|
|
56698
|
+
// no space; first enlarge the buffer
|
|
56699
|
+
buffer_capacity = MaxValue<idx_t>(NextPowerOfTwo(buffer_size + bytes_read), buffer_capacity * 2);
|
|
56700
|
+
|
|
56701
|
+
auto new_buffer = unique_ptr<data_t[]>(new data_t[buffer_capacity]);
|
|
56702
|
+
if (buffer_size > 0) {
|
|
56703
|
+
memcpy(new_buffer.get(), cached_buffer.get(), buffer_size);
|
|
56704
|
+
}
|
|
56705
|
+
cached_buffer = move(new_buffer);
|
|
56706
|
+
}
|
|
56707
|
+
memcpy(cached_buffer.get() + buffer_size, (char *)buffer + result_offset, bytes_read);
|
|
56708
|
+
buffer_size += bytes_read;
|
|
56709
|
+
}
|
|
56710
|
+
|
|
56711
|
+
return result_offset + bytes_read;
|
|
56712
|
+
} else {
|
|
56713
|
+
return file_handle->Read(buffer, nr_bytes);
|
|
56714
|
+
}
|
|
56715
|
+
}
|
|
56716
|
+
|
|
56717
|
+
string ReadLine() {
|
|
56718
|
+
string result;
|
|
56719
|
+
char buffer[1];
|
|
56720
|
+
while (true) {
|
|
56721
|
+
idx_t tuples_read = Read(buffer, 1);
|
|
56722
|
+
if (tuples_read == 0 || buffer[0] == '\n') {
|
|
56723
|
+
return result;
|
|
56724
|
+
}
|
|
56725
|
+
if (buffer[0] != '\r') {
|
|
56726
|
+
result += buffer[0];
|
|
56727
|
+
}
|
|
56728
|
+
}
|
|
56729
|
+
}
|
|
56730
|
+
|
|
56731
|
+
void DisableReset() {
|
|
56732
|
+
this->reset_enabled = false;
|
|
56733
|
+
}
|
|
56734
|
+
|
|
56735
|
+
private:
|
|
56736
|
+
unique_ptr<FileHandle> file_handle;
|
|
56737
|
+
bool reset_enabled = true;
|
|
56738
|
+
bool can_seek = false;
|
|
56739
|
+
bool plain_file_source = false;
|
|
56740
|
+
idx_t file_size = 0;
|
|
56741
|
+
// reset support
|
|
56742
|
+
unique_ptr<data_t[]> cached_buffer;
|
|
56743
|
+
idx_t read_position = 0;
|
|
56744
|
+
idx_t buffer_size = 0;
|
|
56745
|
+
idx_t buffer_capacity = 0;
|
|
56746
|
+
};
|
|
56747
|
+
|
|
56620
56748
|
void BufferedCSVReaderOptions::SetDelimiter(const string &input) {
|
|
56621
56749
|
this->delimiter = StringUtil::Replace(input, "\\t", "\t");
|
|
56622
56750
|
this->has_delimiter = true;
|
|
@@ -56749,6 +56877,13 @@ BufferedCSVReader::BufferedCSVReader(ClientContext &context, BufferedCSVReaderOp
|
|
|
56749
56877
|
requested_types) {
|
|
56750
56878
|
}
|
|
56751
56879
|
|
|
56880
|
+
BufferedCSVReader::~BufferedCSVReader() {
|
|
56881
|
+
}
|
|
56882
|
+
|
|
56883
|
+
idx_t BufferedCSVReader::GetFileSize() {
|
|
56884
|
+
return file_handle ? file_handle->FileSize() : 0;
|
|
56885
|
+
}
|
|
56886
|
+
|
|
56752
56887
|
void BufferedCSVReader::Initialize(const vector<LogicalType> &requested_types) {
|
|
56753
56888
|
PrepareComplexParser();
|
|
56754
56889
|
if (options.auto_detect) {
|
|
@@ -56765,6 +56900,9 @@ void BufferedCSVReader::Initialize(const vector<LogicalType> &requested_types) {
|
|
|
56765
56900
|
SkipRowsAndReadHeader(options.skip_rows, options.header);
|
|
56766
56901
|
}
|
|
56767
56902
|
InitParseChunk(sql_types.size());
|
|
56903
|
+
// we only need reset support during the automatic CSV type detection
|
|
56904
|
+
// since reset support might require caching (in the case of streams), we disable it for the remainder
|
|
56905
|
+
file_handle->DisableReset();
|
|
56768
56906
|
}
|
|
56769
56907
|
|
|
56770
56908
|
void BufferedCSVReader::PrepareComplexParser() {
|
|
@@ -56773,12 +56911,10 @@ void BufferedCSVReader::PrepareComplexParser() {
|
|
|
56773
56911
|
quote_search = TextSearchShiftArray(options.quote);
|
|
56774
56912
|
}
|
|
56775
56913
|
|
|
56776
|
-
unique_ptr<
|
|
56777
|
-
auto
|
|
56778
|
-
|
|
56779
|
-
|
|
56780
|
-
file_size = result->GetFileSize();
|
|
56781
|
-
return result;
|
|
56914
|
+
unique_ptr<CSVFileHandle> BufferedCSVReader::OpenCSV(const BufferedCSVReaderOptions &options) {
|
|
56915
|
+
auto file_handle = fs.OpenFile(options.file_path.c_str(), FileFlags::FILE_FLAGS_READ, FileLockType::NO_LOCK,
|
|
56916
|
+
options.compression, this->opener);
|
|
56917
|
+
return make_unique<CSVFileHandle>(move(file_handle));
|
|
56782
56918
|
}
|
|
56783
56919
|
|
|
56784
56920
|
// Helper function to generate column names
|
|
@@ -56944,7 +57080,7 @@ bool BufferedCSVReader::JumpToNextSample() {
|
|
|
56944
57080
|
// assess if it makes sense to jump, based on size of the first chunk relative to size of the entire file
|
|
56945
57081
|
if (sample_chunk_idx == 0) {
|
|
56946
57082
|
idx_t bytes_first_chunk = bytes_in_chunk;
|
|
56947
|
-
double chunks_fit = (
|
|
57083
|
+
double chunks_fit = (file_handle->FileSize() / (double)bytes_first_chunk);
|
|
56948
57084
|
jumping_samples = chunks_fit >= options.sample_chunks;
|
|
56949
57085
|
|
|
56950
57086
|
// jump back to the beginning
|
|
@@ -56959,7 +57095,7 @@ bool BufferedCSVReader::JumpToNextSample() {
|
|
|
56959
57095
|
|
|
56960
57096
|
// if we deal with any other sources than plaintext files, jumping_samples can be tricky. In that case
|
|
56961
57097
|
// we just read x continuous chunks from the stream TODO: make jumps possible for zipfiles.
|
|
56962
|
-
if (!
|
|
57098
|
+
if (!file_handle->PlainFileSource() || !jumping_samples) {
|
|
56963
57099
|
sample_chunk_idx++;
|
|
56964
57100
|
return true;
|
|
56965
57101
|
}
|
|
@@ -56969,13 +57105,13 @@ bool BufferedCSVReader::JumpToNextSample() {
|
|
|
56969
57105
|
bytes_per_line_avg = ((bytes_per_line_avg * (sample_chunk_idx)) + bytes_per_line) / (sample_chunk_idx + 1);
|
|
56970
57106
|
|
|
56971
57107
|
// if none of the previous conditions were met, we can jump
|
|
56972
|
-
idx_t partition_size = (idx_t)round(
|
|
57108
|
+
idx_t partition_size = (idx_t)round(file_handle->FileSize() / (double)options.sample_chunks);
|
|
56973
57109
|
|
|
56974
57110
|
// calculate offset to end of the current partition
|
|
56975
57111
|
int64_t offset = partition_size - bytes_in_chunk - remaining_bytes_in_buffer;
|
|
56976
57112
|
auto current_pos = file_handle->SeekPosition();
|
|
56977
57113
|
|
|
56978
|
-
if (current_pos + offset <
|
|
57114
|
+
if (current_pos + offset < file_handle->FileSize()) {
|
|
56979
57115
|
// set position in stream and clear failure bits
|
|
56980
57116
|
file_handle->Seek(current_pos + offset);
|
|
56981
57117
|
|
|
@@ -56986,10 +57122,10 @@ bool BufferedCSVReader::JumpToNextSample() {
|
|
|
56986
57122
|
// seek backwards from the end in last chunk and hope to catch the end of the file
|
|
56987
57123
|
// TODO: actually it would be good to make sure that the end of file is being reached, because
|
|
56988
57124
|
// messy end-lines are quite common. For this case, however, we first need a skip_end detection anyways.
|
|
56989
|
-
file_handle->Seek(
|
|
57125
|
+
file_handle->Seek(file_handle->FileSize() - bytes_in_chunk);
|
|
56990
57126
|
|
|
56991
57127
|
// estimate linenr
|
|
56992
|
-
linenr = (idx_t)round((
|
|
57128
|
+
linenr = (idx_t)round((file_handle->FileSize() - bytes_in_chunk) / bytes_per_line_avg);
|
|
56993
57129
|
linenr_estimated = true;
|
|
56994
57130
|
}
|
|
56995
57131
|
|
|
@@ -57143,6 +57279,7 @@ void BufferedCSVReader::DetectDialect(const vector<LogicalType> &requested_types
|
|
|
57143
57279
|
|
|
57144
57280
|
JumpToBeginning(original_options.skip_rows);
|
|
57145
57281
|
sniffed_column_counts.clear();
|
|
57282
|
+
|
|
57146
57283
|
if (!TryParseCSV(ParserMode::SNIFFING_DIALECT)) {
|
|
57147
57284
|
continue;
|
|
57148
57285
|
}
|
|
@@ -72253,7 +72390,7 @@ namespace duckdb {
|
|
|
72253
72390
|
struct VariableReturnBindData : public FunctionData {
|
|
72254
72391
|
LogicalType stype;
|
|
72255
72392
|
|
|
72256
|
-
explicit VariableReturnBindData(LogicalType
|
|
72393
|
+
explicit VariableReturnBindData(const LogicalType &stype_p) : stype(stype_p) {
|
|
72257
72394
|
}
|
|
72258
72395
|
|
|
72259
72396
|
unique_ptr<FunctionData> Copy() override {
|
|
@@ -73604,9 +73741,13 @@ static int64_t TargetTypeCost(const LogicalType &type) {
|
|
|
73604
73741
|
case LogicalTypeId::TIMESTAMP:
|
|
73605
73742
|
return 120;
|
|
73606
73743
|
case LogicalTypeId::VARCHAR:
|
|
73607
|
-
return
|
|
73744
|
+
return 149;
|
|
73608
73745
|
case LogicalTypeId::DECIMAL:
|
|
73609
73746
|
return 104;
|
|
73747
|
+
case LogicalTypeId::STRUCT:
|
|
73748
|
+
case LogicalTypeId::MAP:
|
|
73749
|
+
case LogicalTypeId::LIST:
|
|
73750
|
+
return 160;
|
|
73610
73751
|
default:
|
|
73611
73752
|
return 110;
|
|
73612
73753
|
}
|
|
@@ -75503,6 +75644,10 @@ void DateDiffFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
75503
75644
|
|
|
75504
75645
|
|
|
75505
75646
|
|
|
75647
|
+
|
|
75648
|
+
|
|
75649
|
+
|
|
75650
|
+
|
|
75506
75651
|
namespace duckdb {
|
|
75507
75652
|
|
|
75508
75653
|
bool TryGetDatePartSpecifier(const string &specifier_p, DatePartSpecifier &result) {
|
|
@@ -75569,6 +75714,73 @@ DatePartSpecifier GetDatePartSpecifier(const string &specifier) {
|
|
|
75569
75714
|
return result;
|
|
75570
75715
|
}
|
|
75571
75716
|
|
|
75717
|
+
DatePartSpecifier GetDateTypePartSpecifier(const string &specifier, LogicalType &type) {
|
|
75718
|
+
const auto part = GetDatePartSpecifier(specifier);
|
|
75719
|
+
switch (type.id()) {
|
|
75720
|
+
case LogicalType::TIMESTAMP:
|
|
75721
|
+
case LogicalType::TIMESTAMP_TZ:
|
|
75722
|
+
return part;
|
|
75723
|
+
case LogicalType::DATE:
|
|
75724
|
+
switch (part) {
|
|
75725
|
+
case DatePartSpecifier::YEAR:
|
|
75726
|
+
case DatePartSpecifier::MONTH:
|
|
75727
|
+
case DatePartSpecifier::DAY:
|
|
75728
|
+
case DatePartSpecifier::DECADE:
|
|
75729
|
+
case DatePartSpecifier::CENTURY:
|
|
75730
|
+
case DatePartSpecifier::MILLENNIUM:
|
|
75731
|
+
case DatePartSpecifier::DOW:
|
|
75732
|
+
case DatePartSpecifier::ISODOW:
|
|
75733
|
+
case DatePartSpecifier::WEEK:
|
|
75734
|
+
case DatePartSpecifier::QUARTER:
|
|
75735
|
+
case DatePartSpecifier::DOY:
|
|
75736
|
+
case DatePartSpecifier::YEARWEEK:
|
|
75737
|
+
case DatePartSpecifier::ERA:
|
|
75738
|
+
return part;
|
|
75739
|
+
default:
|
|
75740
|
+
break;
|
|
75741
|
+
}
|
|
75742
|
+
break;
|
|
75743
|
+
case LogicalType::TIME:
|
|
75744
|
+
switch (part) {
|
|
75745
|
+
case DatePartSpecifier::MICROSECONDS:
|
|
75746
|
+
case DatePartSpecifier::MILLISECONDS:
|
|
75747
|
+
case DatePartSpecifier::SECOND:
|
|
75748
|
+
case DatePartSpecifier::MINUTE:
|
|
75749
|
+
case DatePartSpecifier::HOUR:
|
|
75750
|
+
case DatePartSpecifier::EPOCH:
|
|
75751
|
+
case DatePartSpecifier::OFFSET:
|
|
75752
|
+
return part;
|
|
75753
|
+
default:
|
|
75754
|
+
break;
|
|
75755
|
+
}
|
|
75756
|
+
break;
|
|
75757
|
+
case LogicalType::INTERVAL:
|
|
75758
|
+
switch (part) {
|
|
75759
|
+
case DatePartSpecifier::YEAR:
|
|
75760
|
+
case DatePartSpecifier::MONTH:
|
|
75761
|
+
case DatePartSpecifier::DAY:
|
|
75762
|
+
case DatePartSpecifier::DECADE:
|
|
75763
|
+
case DatePartSpecifier::CENTURY:
|
|
75764
|
+
case DatePartSpecifier::QUARTER:
|
|
75765
|
+
case DatePartSpecifier::MILLENNIUM:
|
|
75766
|
+
case DatePartSpecifier::MICROSECONDS:
|
|
75767
|
+
case DatePartSpecifier::MILLISECONDS:
|
|
75768
|
+
case DatePartSpecifier::SECOND:
|
|
75769
|
+
case DatePartSpecifier::MINUTE:
|
|
75770
|
+
case DatePartSpecifier::HOUR:
|
|
75771
|
+
case DatePartSpecifier::EPOCH:
|
|
75772
|
+
return part;
|
|
75773
|
+
default:
|
|
75774
|
+
break;
|
|
75775
|
+
}
|
|
75776
|
+
break;
|
|
75777
|
+
default:
|
|
75778
|
+
break;
|
|
75779
|
+
}
|
|
75780
|
+
|
|
75781
|
+
throw NotImplementedException("\"%s\" units \"%s\" not recognized", LogicalTypeIdToString(type.id()), specifier);
|
|
75782
|
+
}
|
|
75783
|
+
|
|
75572
75784
|
template <class T>
|
|
75573
75785
|
static void LastYearFunction(DataChunk &args, ExpressionState &state, Vector &result) {
|
|
75574
75786
|
int32_t last_year = 0;
|
|
@@ -75902,6 +76114,137 @@ struct DatePart {
|
|
|
75902
76114
|
return PropagateSimpleDatePartStatistics<0, 0>(child_stats);
|
|
75903
76115
|
}
|
|
75904
76116
|
};
|
|
76117
|
+
|
|
76118
|
+
struct StructOperator {
|
|
76119
|
+
using part_codes_t = vector<DatePartSpecifier>;
|
|
76120
|
+
using part_mask_t = uint64_t;
|
|
76121
|
+
|
|
76122
|
+
enum MaskBits : uint8_t {
|
|
76123
|
+
YMD = 1 << 0,
|
|
76124
|
+
DOW = 1 << 1,
|
|
76125
|
+
DOY = 1 << 2,
|
|
76126
|
+
EPOCH = 1 << 3,
|
|
76127
|
+
TIME = 1 << 4,
|
|
76128
|
+
ZONE = 1 << 5
|
|
76129
|
+
};
|
|
76130
|
+
|
|
76131
|
+
static part_mask_t GetMask(const part_codes_t &part_codes) {
|
|
76132
|
+
part_mask_t mask = 0;
|
|
76133
|
+
for (const auto &part_code : part_codes) {
|
|
76134
|
+
switch (part_code) {
|
|
76135
|
+
case DatePartSpecifier::YEAR:
|
|
76136
|
+
case DatePartSpecifier::MONTH:
|
|
76137
|
+
case DatePartSpecifier::DAY:
|
|
76138
|
+
case DatePartSpecifier::DECADE:
|
|
76139
|
+
case DatePartSpecifier::CENTURY:
|
|
76140
|
+
case DatePartSpecifier::MILLENNIUM:
|
|
76141
|
+
case DatePartSpecifier::QUARTER:
|
|
76142
|
+
case DatePartSpecifier::ERA:
|
|
76143
|
+
mask |= YMD;
|
|
76144
|
+
break;
|
|
76145
|
+
case DatePartSpecifier::YEARWEEK:
|
|
76146
|
+
mask |= YMD;
|
|
76147
|
+
mask |= DOW;
|
|
76148
|
+
break;
|
|
76149
|
+
case DatePartSpecifier::DOW:
|
|
76150
|
+
case DatePartSpecifier::ISODOW:
|
|
76151
|
+
case DatePartSpecifier::WEEK:
|
|
76152
|
+
mask |= DOW;
|
|
76153
|
+
break;
|
|
76154
|
+
case DatePartSpecifier::DOY:
|
|
76155
|
+
mask |= DOY;
|
|
76156
|
+
break;
|
|
76157
|
+
case DatePartSpecifier::EPOCH:
|
|
76158
|
+
mask |= EPOCH;
|
|
76159
|
+
break;
|
|
76160
|
+
case DatePartSpecifier::MICROSECONDS:
|
|
76161
|
+
case DatePartSpecifier::MILLISECONDS:
|
|
76162
|
+
case DatePartSpecifier::SECOND:
|
|
76163
|
+
case DatePartSpecifier::MINUTE:
|
|
76164
|
+
case DatePartSpecifier::HOUR:
|
|
76165
|
+
mask |= TIME;
|
|
76166
|
+
break;
|
|
76167
|
+
case DatePartSpecifier::OFFSET:
|
|
76168
|
+
mask |= ZONE;
|
|
76169
|
+
break;
|
|
76170
|
+
}
|
|
76171
|
+
}
|
|
76172
|
+
return mask;
|
|
76173
|
+
}
|
|
76174
|
+
|
|
76175
|
+
template <typename P>
|
|
76176
|
+
static inline P HasPartValue(P *part_values, DatePartSpecifier part) {
|
|
76177
|
+
return part_values[int(part)];
|
|
76178
|
+
}
|
|
76179
|
+
|
|
76180
|
+
template <class TA, class TR>
|
|
76181
|
+
static inline void Operation(TR **part_values, const TA &input, const idx_t idx, const part_mask_t mask) {
|
|
76182
|
+
TR *part_data;
|
|
76183
|
+
// YMD calculations
|
|
76184
|
+
int32_t yyyy = 1970;
|
|
76185
|
+
int32_t mm = 0;
|
|
76186
|
+
int32_t dd = 1;
|
|
76187
|
+
if (mask & YMD) {
|
|
76188
|
+
Date::Convert(input, yyyy, mm, dd);
|
|
76189
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::YEAR))) {
|
|
76190
|
+
part_data[idx] = yyyy;
|
|
76191
|
+
}
|
|
76192
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MONTH))) {
|
|
76193
|
+
part_data[idx] = mm;
|
|
76194
|
+
}
|
|
76195
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::DAY))) {
|
|
76196
|
+
part_data[idx] = dd;
|
|
76197
|
+
}
|
|
76198
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::DECADE))) {
|
|
76199
|
+
part_data[idx] = yyyy / 10;
|
|
76200
|
+
}
|
|
76201
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::CENTURY))) {
|
|
76202
|
+
part_data[idx] = (yyyy - 1) / 100 + 1;
|
|
76203
|
+
}
|
|
76204
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MILLENNIUM))) {
|
|
76205
|
+
part_data[idx] = (yyyy - 1) / 1000 + 1;
|
|
76206
|
+
}
|
|
76207
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::QUARTER))) {
|
|
76208
|
+
part_data[idx] = (mm - 1) / Interval::MONTHS_PER_QUARTER + 1;
|
|
76209
|
+
}
|
|
76210
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::ERA))) {
|
|
76211
|
+
part_data[idx] = yyyy > 0 ? 1 : 0;
|
|
76212
|
+
}
|
|
76213
|
+
}
|
|
76214
|
+
|
|
76215
|
+
// Week calculations
|
|
76216
|
+
int32_t isodow = 0;
|
|
76217
|
+
int32_t ww = 0;
|
|
76218
|
+
if (mask & DOW) {
|
|
76219
|
+
isodow = Date::ExtractISODayOfTheWeek(input);
|
|
76220
|
+
ww = Date::ExtractISOWeekNumber(input);
|
|
76221
|
+
int32_t dow = isodow % 7;
|
|
76222
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::DOW))) {
|
|
76223
|
+
part_data[idx] = dow;
|
|
76224
|
+
}
|
|
76225
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::ISODOW))) {
|
|
76226
|
+
part_data[idx] = isodow;
|
|
76227
|
+
}
|
|
76228
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::WEEK))) {
|
|
76229
|
+
part_data[idx] = ww;
|
|
76230
|
+
}
|
|
76231
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::YEARWEEK))) {
|
|
76232
|
+
part_data[idx] = yyyy * 100 + ww;
|
|
76233
|
+
}
|
|
76234
|
+
}
|
|
76235
|
+
|
|
76236
|
+
if (mask & EPOCH) {
|
|
76237
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::EPOCH))) {
|
|
76238
|
+
part_data[idx] = Date::Epoch(input);
|
|
76239
|
+
}
|
|
76240
|
+
}
|
|
76241
|
+
if (mask & DOY) {
|
|
76242
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::DOY))) {
|
|
76243
|
+
part_data[idx] = Date::ExtractDayOfTheYear(input);
|
|
76244
|
+
}
|
|
76245
|
+
}
|
|
76246
|
+
}
|
|
76247
|
+
};
|
|
75905
76248
|
};
|
|
75906
76249
|
|
|
75907
76250
|
template <>
|
|
@@ -76198,7 +76541,7 @@ int64_t DatePart::OffsetOperator::Operation(timestamp_t input) {
|
|
|
76198
76541
|
|
|
76199
76542
|
template <>
|
|
76200
76543
|
int64_t DatePart::OffsetOperator::Operation(interval_t input) {
|
|
76201
|
-
|
|
76544
|
+
throw NotImplementedException("\"interval\" units \"offset\" not recognized");
|
|
76202
76545
|
}
|
|
76203
76546
|
|
|
76204
76547
|
template <>
|
|
@@ -76206,7 +76549,110 @@ int64_t DatePart::OffsetOperator::Operation(dtime_t input) {
|
|
|
76206
76549
|
return 0;
|
|
76207
76550
|
}
|
|
76208
76551
|
|
|
76209
|
-
template
|
|
76552
|
+
template <>
|
|
76553
|
+
void DatePart::StructOperator::Operation(int64_t **part_values, const dtime_t &input, const idx_t idx,
|
|
76554
|
+
const part_mask_t mask) {
|
|
76555
|
+
int64_t *part_data;
|
|
76556
|
+
if (mask & TIME) {
|
|
76557
|
+
const auto micros = MicrosecondsOperator::Operation<dtime_t, int64_t>(input);
|
|
76558
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MICROSECONDS))) {
|
|
76559
|
+
part_data[idx] = micros;
|
|
76560
|
+
}
|
|
76561
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MILLISECONDS))) {
|
|
76562
|
+
part_data[idx] = micros / Interval::MICROS_PER_MSEC;
|
|
76563
|
+
}
|
|
76564
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::SECOND))) {
|
|
76565
|
+
part_data[idx] = micros / Interval::MICROS_PER_SEC;
|
|
76566
|
+
}
|
|
76567
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MINUTE))) {
|
|
76568
|
+
part_data[idx] = MinutesOperator::Operation<dtime_t, int64_t>(input);
|
|
76569
|
+
}
|
|
76570
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::HOUR))) {
|
|
76571
|
+
part_data[idx] = HoursOperator::Operation<dtime_t, int64_t>(input);
|
|
76572
|
+
}
|
|
76573
|
+
}
|
|
76574
|
+
|
|
76575
|
+
if (mask & EPOCH) {
|
|
76576
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::EPOCH))) {
|
|
76577
|
+
part_data[idx] = EpochOperator::Operation<dtime_t, int64_t>(input);
|
|
76578
|
+
;
|
|
76579
|
+
}
|
|
76580
|
+
}
|
|
76581
|
+
|
|
76582
|
+
if (mask & ZONE) {
|
|
76583
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::OFFSET))) {
|
|
76584
|
+
part_data[idx] = 0;
|
|
76585
|
+
}
|
|
76586
|
+
}
|
|
76587
|
+
}
|
|
76588
|
+
|
|
76589
|
+
template <>
|
|
76590
|
+
void DatePart::StructOperator::Operation(int64_t **part_values, const timestamp_t &input, const idx_t idx,
|
|
76591
|
+
const part_mask_t mask) {
|
|
76592
|
+
date_t d;
|
|
76593
|
+
dtime_t t;
|
|
76594
|
+
Timestamp::Convert(input, d, t);
|
|
76595
|
+
// Time first because they both define epoch.
|
|
76596
|
+
Operation(part_values, t, idx, mask);
|
|
76597
|
+
Operation(part_values, d, idx, mask);
|
|
76598
|
+
}
|
|
76599
|
+
|
|
76600
|
+
template <>
|
|
76601
|
+
void DatePart::StructOperator::Operation(int64_t **part_values, const interval_t &input, const idx_t idx,
|
|
76602
|
+
const part_mask_t mask) {
|
|
76603
|
+
int64_t *part_data;
|
|
76604
|
+
if (mask & YMD) {
|
|
76605
|
+
const auto mm = input.months % Interval::MONTHS_PER_YEAR;
|
|
76606
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::YEAR))) {
|
|
76607
|
+
part_data[idx] = input.months / Interval::MONTHS_PER_YEAR;
|
|
76608
|
+
}
|
|
76609
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MONTH))) {
|
|
76610
|
+
part_data[idx] = mm;
|
|
76611
|
+
}
|
|
76612
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::DAY))) {
|
|
76613
|
+
part_data[idx] = input.days;
|
|
76614
|
+
}
|
|
76615
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::DECADE))) {
|
|
76616
|
+
part_data[idx] = input.months / Interval::MONTHS_PER_DECADE;
|
|
76617
|
+
}
|
|
76618
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::CENTURY))) {
|
|
76619
|
+
part_data[idx] = input.months / Interval::MONTHS_PER_CENTURY;
|
|
76620
|
+
}
|
|
76621
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MILLENNIUM))) {
|
|
76622
|
+
part_data[idx] = input.months / Interval::MONTHS_PER_MILLENIUM;
|
|
76623
|
+
}
|
|
76624
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::QUARTER))) {
|
|
76625
|
+
part_data[idx] = mm / Interval::MONTHS_PER_QUARTER + 1;
|
|
76626
|
+
}
|
|
76627
|
+
}
|
|
76628
|
+
|
|
76629
|
+
if (mask & TIME) {
|
|
76630
|
+
const auto micros = MicrosecondsOperator::Operation<interval_t, int64_t>(input);
|
|
76631
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MICROSECONDS))) {
|
|
76632
|
+
part_data[idx] = micros;
|
|
76633
|
+
}
|
|
76634
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MILLISECONDS))) {
|
|
76635
|
+
part_data[idx] = micros / Interval::MICROS_PER_MSEC;
|
|
76636
|
+
}
|
|
76637
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::SECOND))) {
|
|
76638
|
+
part_data[idx] = micros / Interval::MICROS_PER_SEC;
|
|
76639
|
+
}
|
|
76640
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::MINUTE))) {
|
|
76641
|
+
part_data[idx] = MinutesOperator::Operation<interval_t, int64_t>(input);
|
|
76642
|
+
}
|
|
76643
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::HOUR))) {
|
|
76644
|
+
part_data[idx] = HoursOperator::Operation<interval_t, int64_t>(input);
|
|
76645
|
+
}
|
|
76646
|
+
}
|
|
76647
|
+
|
|
76648
|
+
if (mask & EPOCH) {
|
|
76649
|
+
if ((part_data = HasPartValue(part_values, DatePartSpecifier::EPOCH))) {
|
|
76650
|
+
part_data[idx] = EpochOperator::Operation<interval_t, int64_t>(input);
|
|
76651
|
+
}
|
|
76652
|
+
}
|
|
76653
|
+
}
|
|
76654
|
+
|
|
76655
|
+
template <typename T>
|
|
76210
76656
|
static int64_t ExtractElement(DatePartSpecifier type, T element) {
|
|
76211
76657
|
switch (type) {
|
|
76212
76658
|
case DatePartSpecifier::YEAR:
|
|
@@ -76346,6 +76792,164 @@ struct DayNameOperator {
|
|
|
76346
76792
|
}
|
|
76347
76793
|
};
|
|
76348
76794
|
|
|
76795
|
+
struct StructDatePart {
|
|
76796
|
+
using part_codes_t = vector<DatePartSpecifier>;
|
|
76797
|
+
|
|
76798
|
+
struct BindData : public VariableReturnBindData {
|
|
76799
|
+
part_codes_t part_codes;
|
|
76800
|
+
|
|
76801
|
+
explicit BindData(const LogicalType &stype, const part_codes_t &part_codes_p)
|
|
76802
|
+
: VariableReturnBindData(stype), part_codes(part_codes_p) {
|
|
76803
|
+
}
|
|
76804
|
+
|
|
76805
|
+
unique_ptr<FunctionData> Copy() override {
|
|
76806
|
+
return make_unique<BindData>(stype, part_codes);
|
|
76807
|
+
}
|
|
76808
|
+
};
|
|
76809
|
+
|
|
76810
|
+
static unique_ptr<FunctionData> Bind(ClientContext &context, ScalarFunction &bound_function,
|
|
76811
|
+
vector<unique_ptr<Expression>> &arguments) {
|
|
76812
|
+
// collect names and deconflict, construct return type
|
|
76813
|
+
if (!arguments[0]->IsFoldable()) {
|
|
76814
|
+
throw BinderException("%s can only take constant lists of part names", bound_function.name);
|
|
76815
|
+
}
|
|
76816
|
+
|
|
76817
|
+
case_insensitive_set_t name_collision_set;
|
|
76818
|
+
child_list_t<LogicalType> struct_children;
|
|
76819
|
+
part_codes_t part_codes;
|
|
76820
|
+
|
|
76821
|
+
Value parts_list = ExpressionExecutor::EvaluateScalar(*arguments[0]);
|
|
76822
|
+
if (parts_list.type().id() == LogicalTypeId::LIST) {
|
|
76823
|
+
if (parts_list.list_value.empty()) {
|
|
76824
|
+
throw BinderException("%s requires non-empty lists of part names", bound_function.name);
|
|
76825
|
+
}
|
|
76826
|
+
for (const auto &part_value : parts_list.list_value) {
|
|
76827
|
+
if (part_value.is_null) {
|
|
76828
|
+
throw BinderException("NULL struct entry name in %s", bound_function.name);
|
|
76829
|
+
}
|
|
76830
|
+
const auto part_name = part_value.ToString();
|
|
76831
|
+
const auto part_code = GetDateTypePartSpecifier(part_name, arguments[1]->return_type);
|
|
76832
|
+
if (name_collision_set.find(part_name) != name_collision_set.end()) {
|
|
76833
|
+
throw BinderException("Duplicate struct entry name \"%s\" in %s", part_name, bound_function.name);
|
|
76834
|
+
}
|
|
76835
|
+
name_collision_set.insert(part_name);
|
|
76836
|
+
part_codes.emplace_back(part_code);
|
|
76837
|
+
struct_children.emplace_back(make_pair(part_name, LogicalType::BIGINT));
|
|
76838
|
+
}
|
|
76839
|
+
} else {
|
|
76840
|
+
throw BinderException("%s can only take constant lists of part names", bound_function.name);
|
|
76841
|
+
}
|
|
76842
|
+
|
|
76843
|
+
arguments.erase(arguments.begin());
|
|
76844
|
+
bound_function.arguments.erase(bound_function.arguments.begin());
|
|
76845
|
+
bound_function.return_type = LogicalType::STRUCT(move(struct_children));
|
|
76846
|
+
return make_unique<BindData>(bound_function.return_type, part_codes);
|
|
76847
|
+
}
|
|
76848
|
+
|
|
76849
|
+
template <typename INPUT_TYPE>
|
|
76850
|
+
static void Function(DataChunk &args, ExpressionState &state, Vector &result) {
|
|
76851
|
+
auto &func_expr = (BoundFunctionExpression &)state.expr;
|
|
76852
|
+
auto &info = (BindData &)*func_expr.bind_info;
|
|
76853
|
+
D_ASSERT(args.ColumnCount() == 1);
|
|
76854
|
+
|
|
76855
|
+
const auto count = args.size();
|
|
76856
|
+
Vector &input = args.data[0];
|
|
76857
|
+
vector<int64_t *> part_values(int(DatePartSpecifier::OFFSET) + 1, nullptr);
|
|
76858
|
+
const auto part_mask = DatePart::StructOperator::GetMask(info.part_codes);
|
|
76859
|
+
|
|
76860
|
+
auto &child_entries = StructVector::GetEntries(result);
|
|
76861
|
+
|
|
76862
|
+
// The first computer of a part "owns" it
|
|
76863
|
+
// and other requestors just reference the owner
|
|
76864
|
+
vector<size_t> owners(int(DatePartSpecifier::OFFSET) + 1, child_entries.size());
|
|
76865
|
+
for (size_t col = 0; col < child_entries.size(); ++col) {
|
|
76866
|
+
const auto part_index = size_t(info.part_codes[col]);
|
|
76867
|
+
if (owners[part_index] == child_entries.size()) {
|
|
76868
|
+
owners[part_index] = col;
|
|
76869
|
+
}
|
|
76870
|
+
}
|
|
76871
|
+
|
|
76872
|
+
if (input.GetVectorType() == VectorType::CONSTANT_VECTOR) {
|
|
76873
|
+
result.SetVectorType(VectorType::CONSTANT_VECTOR);
|
|
76874
|
+
|
|
76875
|
+
if (ConstantVector::IsNull(input)) {
|
|
76876
|
+
ConstantVector::SetNull(result, true);
|
|
76877
|
+
} else {
|
|
76878
|
+
ConstantVector::SetNull(result, false);
|
|
76879
|
+
for (size_t col = 0; col < child_entries.size(); ++col) {
|
|
76880
|
+
auto &child_entry = child_entries[col];
|
|
76881
|
+
ConstantVector::SetNull(*child_entry, false);
|
|
76882
|
+
const auto part_index = size_t(info.part_codes[col]);
|
|
76883
|
+
if (owners[part_index] == col) {
|
|
76884
|
+
part_values[part_index] = ConstantVector::GetData<int64_t>(*child_entry);
|
|
76885
|
+
}
|
|
76886
|
+
}
|
|
76887
|
+
auto tdata = ConstantVector::GetData<INPUT_TYPE>(input);
|
|
76888
|
+
DatePart::StructOperator::Operation(part_values.data(), tdata[0], 0, part_mask);
|
|
76889
|
+
}
|
|
76890
|
+
} else {
|
|
76891
|
+
VectorData rdata;
|
|
76892
|
+
input.Orrify(count, rdata);
|
|
76893
|
+
|
|
76894
|
+
const auto &arg_valid = rdata.validity;
|
|
76895
|
+
auto tdata = (const INPUT_TYPE *)rdata.data;
|
|
76896
|
+
|
|
76897
|
+
// Start with a valid flat vector
|
|
76898
|
+
result.SetVectorType(VectorType::FLAT_VECTOR);
|
|
76899
|
+
auto &res_valid = FlatVector::Validity(result);
|
|
76900
|
+
if (res_valid.GetData()) {
|
|
76901
|
+
res_valid.SetAllValid(count);
|
|
76902
|
+
}
|
|
76903
|
+
|
|
76904
|
+
// Start with valid children
|
|
76905
|
+
for (size_t col = 0; col < child_entries.size(); ++col) {
|
|
76906
|
+
auto &child_entry = child_entries[col];
|
|
76907
|
+
child_entry->SetVectorType(VectorType::FLAT_VECTOR);
|
|
76908
|
+
auto &child_validity = FlatVector::Validity(*child_entry);
|
|
76909
|
+
if (child_validity.GetData()) {
|
|
76910
|
+
child_validity.SetAllValid(count);
|
|
76911
|
+
}
|
|
76912
|
+
|
|
76913
|
+
// Pre-multiplex
|
|
76914
|
+
const auto part_index = size_t(info.part_codes[col]);
|
|
76915
|
+
if (owners[part_index] == col) {
|
|
76916
|
+
part_values[part_index] = FlatVector::GetData<int64_t>(*child_entry);
|
|
76917
|
+
}
|
|
76918
|
+
}
|
|
76919
|
+
|
|
76920
|
+
for (idx_t i = 0; i < count; ++i) {
|
|
76921
|
+
const auto idx = rdata.sel->get_index(i);
|
|
76922
|
+
if (arg_valid.RowIsValid(idx)) {
|
|
76923
|
+
DatePart::StructOperator::Operation(part_values.data(), tdata[idx], idx, part_mask);
|
|
76924
|
+
} else {
|
|
76925
|
+
res_valid.SetInvalid(idx);
|
|
76926
|
+
for (auto &child_entry : child_entries) {
|
|
76927
|
+
FlatVector::Validity(*child_entry).SetInvalid(idx);
|
|
76928
|
+
}
|
|
76929
|
+
}
|
|
76930
|
+
}
|
|
76931
|
+
}
|
|
76932
|
+
|
|
76933
|
+
// Reference any duplicate parts
|
|
76934
|
+
for (size_t col = 0; col < child_entries.size(); ++col) {
|
|
76935
|
+
const auto part_index = size_t(info.part_codes[col]);
|
|
76936
|
+
const auto owner = owners[part_index];
|
|
76937
|
+
if (owner != col) {
|
|
76938
|
+
child_entries[col]->Reference(*child_entries[owner]);
|
|
76939
|
+
}
|
|
76940
|
+
}
|
|
76941
|
+
|
|
76942
|
+
result.Verify(count);
|
|
76943
|
+
}
|
|
76944
|
+
|
|
76945
|
+
template <typename INPUT_TYPE>
|
|
76946
|
+
static ScalarFunction GetFunction(const LogicalType &temporal_type) {
|
|
76947
|
+
auto part_type = LogicalType::LIST(LogicalType::VARCHAR);
|
|
76948
|
+
auto result_type = LogicalType::STRUCT({});
|
|
76949
|
+
return ScalarFunction({part_type, temporal_type}, result_type, Function<INPUT_TYPE>, false, Bind);
|
|
76950
|
+
}
|
|
76951
|
+
};
|
|
76952
|
+
|
|
76349
76953
|
void DatePartFun::RegisterFunction(BuiltinFunctions &set) {
|
|
76350
76954
|
// register the individual operators
|
|
76351
76955
|
AddGenericDatePartOperator(set, "year", LastYearFunction<date_t>, LastYearFunction<timestamp_t>,
|
|
@@ -76412,6 +77016,13 @@ void DatePartFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
76412
77016
|
ScalarFunction({LogicalType::VARCHAR, LogicalType::TIME}, LogicalType::BIGINT, DatePartFunction<dtime_t>));
|
|
76413
77017
|
date_part.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::INTERVAL}, LogicalType::BIGINT,
|
|
76414
77018
|
DatePartFunction<interval_t>));
|
|
77019
|
+
|
|
77020
|
+
// struct variants
|
|
77021
|
+
date_part.AddFunction(StructDatePart::GetFunction<date_t>(LogicalType::DATE));
|
|
77022
|
+
date_part.AddFunction(StructDatePart::GetFunction<timestamp_t>(LogicalType::TIMESTAMP));
|
|
77023
|
+
date_part.AddFunction(StructDatePart::GetFunction<dtime_t>(LogicalType::TIME));
|
|
77024
|
+
date_part.AddFunction(StructDatePart::GetFunction<interval_t>(LogicalType::INTERVAL));
|
|
77025
|
+
|
|
76415
77026
|
set.AddFunction(date_part);
|
|
76416
77027
|
date_part.name = "datepart";
|
|
76417
77028
|
set.AddFunction(date_part);
|
|
@@ -91542,7 +92153,7 @@ static unique_ptr<FunctionOperatorData> ReadCSVInit(ClientContext &context, cons
|
|
|
91542
92153
|
result->csv_reader = make_unique<BufferedCSVReader>(context, bind_data.options, bind_data.sql_types);
|
|
91543
92154
|
}
|
|
91544
92155
|
bind_data.bytes_read = 0;
|
|
91545
|
-
bind_data.file_size = result->csv_reader->
|
|
92156
|
+
bind_data.file_size = result->csv_reader->GetFileSize();
|
|
91546
92157
|
result->file_index = 1;
|
|
91547
92158
|
return move(result);
|
|
91548
92159
|
}
|