Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions c++/include/orc/Reader.hh
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,16 @@ namespace orc {
*/
const std::string& getTimezoneName() const;

/**
* Use the writer timezone when reading timestamp values.
*/
RowReaderOptions& setUseWriterTimezone(bool useWriterTimezone);

/**
* Get whether to use the writer timezone when reading timestamp values.
*/
bool getUseWriterTimezone() const;

/**
* Get the IdReadIntentMap map that was supplied by client.
*/
Expand Down
12 changes: 12 additions & 0 deletions c++/src/Options.hh
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ namespace orc {
bool enableLazyDecoding;
std::shared_ptr<SearchArgument> sargs;
std::string readerTimezone;
bool useWriterTimezone;
RowReaderOptions::IdReadIntentMap idReadIntentMap;
bool useTightNumericVector;
std::shared_ptr<Type> readType;
Expand All @@ -167,6 +168,7 @@ namespace orc {
forcedScaleOnHive11Decimal = 6;
enableLazyDecoding = false;
readerTimezone = "GMT";
useWriterTimezone = false;
useTightNumericVector = false;
throwOnSchemaEvolutionOverflow = false;
enableAsyncPrefetch = false;
Expand Down Expand Up @@ -318,13 +320,23 @@ namespace orc {

RowReaderOptions& RowReaderOptions::setTimezoneName(const std::string& zoneName) {
privateBits_->readerTimezone = zoneName;
privateBits_->useWriterTimezone = false;
return *this;
}

const std::string& RowReaderOptions::getTimezoneName() const {
return privateBits_->readerTimezone;
}

RowReaderOptions& RowReaderOptions::setUseWriterTimezone(bool useWriterTimezone) {
privateBits_->useWriterTimezone = useWriterTimezone;
return *this;
}

bool RowReaderOptions::getUseWriterTimezone() const {
return privateBits_->useWriterTimezone;
}

const RowReaderOptions::IdReadIntentMap RowReaderOptions::getIdReadIntentMap() const {
return privateBits_->idReadIntentMap;
}
Expand Down
7 changes: 5 additions & 2 deletions c++/src/Reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,9 @@ namespace orc {
footer_(contents_->footer.get()),
firstRowOfStripe_(*contents_->pool, 0),
enableEncodedBlock_(opts.getEnableLazyDecoding()),
readerTimezone_(getTimezoneByName(opts.getTimezoneName())),
readerTimezone_(opts.getUseWriterTimezone() ? localTimezone_
: getTimezoneByName(opts.getTimezoneName())),
useWriterTimezone_(opts.getUseWriterTimezone()),
schemaEvolution_(opts.getReadType(), contents_->schema.get()) {
uint64_t numberOfStripes;
numberOfStripes = static_cast<uint64_t>(footer_->stripes_size());
Expand Down Expand Up @@ -1366,7 +1368,8 @@ namespace orc {
: localTimezone_;
StripeStreamsImpl stripeStreams(*this, currentStripe_, currentStripeInfo_,
currentStripeFooter_, currentStripeInfo_.offset(),
*contents_->stream, writerTimezone, readerTimezone_);
*contents_->stream, writerTimezone,
useWriterTimezone_ ? writerTimezone : readerTimezone_);
reader_ = buildReader(*contents_->schema, stripeStreams, useTightNumericVector_,
throwOnSchemaEvolutionOverflow_, /*convertToReadType=*/true);

Expand Down
1 change: 1 addition & 0 deletions c++/src/Reader.hh
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ namespace orc {

// desired timezone to return data of timestamp types.
const Timezone& readerTimezone_;
const bool useWriterTimezone_;

// match read and file types
SchemaEvolution schemaEvolution_;
Expand Down
38 changes: 38 additions & 0 deletions c++/test/TestWriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,44 @@ namespace orc {
"2014-06-06 12:34:56", IS_DST);
}

TEST_P(WriterTest, readTimestampWithWriterTimezone) {
MemoryOutputStream memStream(DEFAULT_MEM_STREAM_SIZE);
MemoryPool* pool = getDefaultPool();
std::unique_ptr<Type> type(Type::buildTypeFromString("struct<col1:timestamp>"));

std::unique_ptr<Writer> writer =
createWriter(16 * 1024, 64, 1024, CompressionKind_ZLIB, *type, pool, &memStream,
fileVersion, 0, "Asia/Shanghai");
std::unique_ptr<ColumnVectorBatch> batch = writer->createRowBatch(1);
auto* structBatch = dynamic_cast<StructVectorBatch*>(batch.get());
auto* tsBatch = dynamic_cast<TimestampVectorBatch*>(structBatch->fields[0]);
tsBatch->data[0] = 0;
tsBatch->nanoseconds[0] = 123000000;
structBatch->numElements = 1;
tsBatch->numElements = 1;
writer->add(*batch);
writer->close();

auto readTimestamp = [&](bool useWriterTimezone) {
auto inStream =
std::make_unique<MemoryInputStream>(memStream.getData(), memStream.getLength());
std::unique_ptr<Reader> reader = createReader(pool, std::move(inStream));
RowReaderOptions rowReaderOptions;
rowReaderOptions.setTimezoneName("GMT");
rowReaderOptions.setUseWriterTimezone(useWriterTimezone);
std::unique_ptr<RowReader> rowReader = reader->createRowReader(rowReaderOptions);
std::unique_ptr<ColumnVectorBatch> readBatch = rowReader->createRowBatch(1);
EXPECT_TRUE(rowReader->next(*readBatch));
auto* readStructBatch = dynamic_cast<StructVectorBatch*>(readBatch.get());
auto* readTsBatch = dynamic_cast<TimestampVectorBatch*>(readStructBatch->fields[0]);
EXPECT_EQ(123000000, readTsBatch->nanoseconds[0]);
return readTsBatch->data[0];
};

EXPECT_EQ(8 * 60 * 60, readTimestamp(/*useWriterTimezone=*/false));
EXPECT_EQ(0, readTimestamp(/*useWriterTimezone=*/true));
}

// Test that the ORC-306 compensation (-1s for pre-1970 timestamps with
// nanos > 999999) is applied BEFORE timezone conversion in the Reader.
//
Expand Down
Loading