From b910d884f0f295e482d70f87604f96a2ac72d6d9 Mon Sep 17 00:00:00 2001 From: dgibson Date: Mon, 30 Jun 2025 16:19:39 +0000 Subject: [PATCH 01/15] Implement support for marshalling columns to velox Timestamp type. --- velox/connectors/clp/ClpDataSource.cpp | 3 + .../connectors/clp/search_lib/CMakeLists.txt | 1 + velox/connectors/clp/search_lib/ClpCursor.cpp | 4 + velox/connectors/clp/search_lib/ClpCursor.h | 10 +- .../clp/search_lib/ClpVectorLoader.cpp | 165 ++++++++++++++++++ .../clp/search_lib/ClpVectorLoader.h | 10 ++ 6 files changed, 192 insertions(+), 1 deletion(-) diff --git a/velox/connectors/clp/ClpDataSource.cpp b/velox/connectors/clp/ClpDataSource.cpp index 6bc4d1d1414..d41c69b99c1 100644 --- a/velox/connectors/clp/ClpDataSource.cpp +++ b/velox/connectors/clp/ClpDataSource.cpp @@ -93,6 +93,9 @@ void ClpDataSource::addFieldsRecursively( case TypeKind::ARRAY: clpColumnType = search_lib::ColumnType::Array; break; + case TypeKind::TIMESTAMP: + clpColumnType = search_lib::ColumnType::Timestamp; + break; default: VELOX_USER_FAIL("Type not supported: {}", columnType->name()); } diff --git a/velox/connectors/clp/search_lib/CMakeLists.txt b/velox/connectors/clp/search_lib/CMakeLists.txt index 7f163d0aa2a..aaf3a40d466 100644 --- a/velox/connectors/clp/search_lib/CMakeLists.txt +++ b/velox/connectors/clp/search_lib/CMakeLists.txt @@ -32,3 +32,4 @@ velox_link_libraries( clp_s::search::kql velox_vector) target_compile_features(clp-s-search PRIVATE cxx_std_20) + diff --git a/velox/connectors/clp/search_lib/ClpCursor.cpp b/velox/connectors/clp/search_lib/ClpCursor.cpp index bab940c92c3..364929dd144 100644 --- a/velox/connectors/clp/search_lib/ClpCursor.cpp +++ b/velox/connectors/clp/search_lib/ClpCursor.cpp @@ -213,6 +213,10 @@ ErrorCode ClpCursor::loadArchive() { case ColumnType::Array: columnDescriptor->set_matching_types(LiteralType::ArrayT); break; + case ColumnType::Timestamp: + columnDescriptor->set_matching_types( + LiteralType::EpochDateT | LiteralType::IntegerT | + LiteralType::FloatT); default: break; } diff --git a/velox/connectors/clp/search_lib/ClpCursor.h b/velox/connectors/clp/search_lib/ClpCursor.h index 43db49c7841..81c224f5e0f 100644 --- a/velox/connectors/clp/search_lib/ClpCursor.h +++ b/velox/connectors/clp/search_lib/ClpCursor.h @@ -49,7 +49,15 @@ enum class ErrorCode { Success }; -enum class ColumnType { String, Integer, Float, Array, Boolean, Unknown = -1 }; +enum class ColumnType { + String, + Integer, + Float, + Array, + Boolean, + Timestamp, + Unknown = -1 +}; struct Field { ColumnType type; diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp index be73e842d73..a310f52b057 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp @@ -14,16 +14,106 @@ * limitations under the License. */ +#include +#include #include #include "clp_s/ColumnReader.hpp" +#include "clp_s/SchemaTree.hpp" #include "velox/connectors/clp/search_lib/ClpVectorLoader.h" +#include "velox/type/Timestamp.h" #include "velox/vector/ComplexVector.h" #include "velox/vector/FlatVector.h" namespace facebook::velox::connector::clp::search_lib { +namespace { +enum class TimestampPrecision : uint8_t { + Seconds, + Milliseconds, + Microseconds, + Nanoseconds +}; + +/** + * Estimates the precision of an epoch timestamp as seconds, milliseconds, + * or nanoseconds. + * + * This heuristic relies on the fact that 1 year of epoch nanoseconds is + * approximately 1000 years of epoch microseconds and so on. This heuristic + * can be unreliable for timestamps sufficiently close to the epoch, but should + * otherwise be accurate for the next 1000 years. + * + * @param timestamp + * @return the estimated timestamp precision + */ +template +auto estimatePrecision(T timestamp) -> TimestampPrecision { + constexpr int64_t kEpochMilliseconds1971{31536000000}; + constexpr int64_t kEpochMicroseconds1971{31536000000000}; + constexpr int64_t kEpochNanoseconds1971{31536000000000}; + if (timestamp > kEpochNanoseconds1971) { + return TimestampPrecision::Nanoseconds; + } else if (timestamp > kEpochMicroseconds1971) { + return TimestampPrecision::Microseconds; + } else if (timestamp > kEpochMilliseconds1971) { + return TimestampPrecision::Milliseconds; + } else if (timestamp > -kEpochMilliseconds1971) { + return TimestampPrecision::Seconds; + } else if (timestamp > -kEpochMicroseconds1971) { + return TimestampPrecision::Milliseconds; + } else if (timestamp > -kEpochNanoseconds1971) { + return TimestampPrecision::Microseconds; + } else { + return TimestampPrecision::Nanoseconds; + } +} + +auto convertToVeloxTimestamp(double timestamp) -> Timestamp { + switch (estimatePrecision(timestamp)) { + case TimestampPrecision::Nanoseconds: + timestamp /= Timestamp::kNanosInSecond; + break; + case TimestampPrecision::Microseconds: + timestamp /= Timestamp::kMicrosecondsInSecond; + break; + case TimestampPrecision::Milliseconds: + timestamp /= Timestamp::kMillisecondsInSecond; + break; + case TimestampPrecision::Seconds: + break; + } + double seconds{floor(timestamp)}; + double nanoseconds{(timestamp - seconds) * Timestamp::kNanosInSecond}; + return Timestamp( + static_cast(seconds), static_cast(nanoseconds)); +} + +auto convertToVeloxTimestamp(int64_t timestamp) -> Timestamp { + switch (estimatePrecision(timestamp)) { + case TimestampPrecision::Nanoseconds: + break; + case TimestampPrecision::Microseconds: + timestamp *= Timestamp::kNanosecondsInMicrosecond; + break; + case TimestampPrecision::Milliseconds: + timestamp *= Timestamp::kNanosecondsInMillisecond; + break; + case TimestampPrecision::Seconds: + timestamp *= Timestamp::kNanosInSecond; + break; + } + int64_t seconds{timestamp / Timestamp::kNanosInSecond}; + int64_t nanoseconds{timestamp - seconds * Timestamp::kNanosInSecond}; + if (nanoseconds < 0) { + seconds -= 1; + nanoseconds += Timestamp::kNanosInSecond; + } + return Timestamp(seconds, static_cast(nanoseconds)); +} +} // namespace + ClpVectorLoader::ClpVectorLoader( clp_s::BaseColumnReader* columnReader, ColumnType nodeType, @@ -57,6 +147,51 @@ void ClpVectorLoader::populateData(RowSet rows, VectorPtr vector) { } } +template +void ClpVectorLoader::populateTimestampData( + RowSet rows, + FlatVector* vector) { + bool supportedNodeType{false}; + switch (Type) { + case clp_s::NodeType::Float: + case clp_s::NodeType::Integer: + case clp_s::NodeType::DateString: + supportedNodeType = true; + break; + default: + break; + } + if (columnReader_ == nullptr || false == supportedNodeType) { + for (int vectorIndex : rows) { + vector->setNull(vectorIndex, true); + } + return; + } + + for (int vectorIndex : rows) { + auto messageIndex = (*filteredRowIndices_)[vectorIndex]; + + if (clp_s::NodeType::Float == Type) { + auto reader = static_cast(columnReader_); + vector->set( + vectorIndex, + convertToVeloxTimestamp( + std::get(reader->extract_value(messageIndex)))); + } else if (clp_s::NodeType::Integer == Type) { + auto reader = static_cast(columnReader_); + vector->set( + vectorIndex, + convertToVeloxTimestamp( + std::get(reader->extract_value(messageIndex)))); + } else { + auto reader = static_cast(columnReader_); + vector->set( + vectorIndex, + convertToVeloxTimestamp(reader->get_encoded_time(messageIndex))); + } + } +} + void ClpVectorLoader::loadInternal( RowSet rows, ValueHook* hook, @@ -142,6 +277,23 @@ void ClpVectorLoader::loadInternal( } break; } + case ColumnType::Timestamp: { + auto timestampVector = vector->asFlatVector(); + if (nullptr != dynamic_cast(columnReader_)) { + populateTimestampData(rows, timestampVector); + } else if ( + nullptr != + dynamic_cast(columnReader_)) { + populateTimestampData( + rows, timestampVector); + } else if ( + nullptr != dynamic_cast(columnReader_)) { + populateTimestampData(rows, timestampVector); + } else { + populateTimestampData(rows, timestampVector); + } + break; + } default: VELOX_FAIL("Unsupported column type"); } @@ -160,5 +312,18 @@ template void ClpVectorLoader::populateData( template void ClpVectorLoader::populateData( RowSet rows, FlatVector* vector); +template void ClpVectorLoader::populateTimestampData( + RowSet rows, + FlatVector* vector); +template void ClpVectorLoader::populateTimestampData( + RowSet rows, + FlatVector* vector); +template void +ClpVectorLoader::populateTimestampData( + RowSet rows, + FlatVector* vector); +template void ClpVectorLoader::populateTimestampData( + RowSet rows, + FlatVector* vector); } // namespace facebook::velox::connector::clp::search_lib diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.h b/velox/connectors/clp/search_lib/ClpVectorLoader.h index ab57b52dfd9..36af6d7b807 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.h +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.h @@ -16,7 +16,12 @@ #pragma once +#include "clp_s/ColumnReader.hpp" +#include "clp_s/SchemaTree.hpp" + #include "velox/connectors/clp/search_lib/ClpCursor.h" +#include "velox/type/Timestamp.h" +#include "velox/vector/FlatVector.h" #include "velox/vector/LazyVector.h" namespace clp_s { @@ -45,6 +50,11 @@ class ClpVectorLoader : public VectorLoader { template void populateData(RowSet rows, VectorPtr vector); + template + void populateTimestampData( + RowSet rows, + FlatVector* vector); + clp_s::BaseColumnReader* columnReader_; ColumnType nodeType_; std::shared_ptr> filteredRowIndices_; From 247751a2d0e3d174213ccc6a8c159860eb1924f5 Mon Sep 17 00:00:00 2001 From: dgibson Date: Thu, 10 Jul 2025 13:53:38 -0400 Subject: [PATCH 02/15] Get rid of extra newline in cmakelists --- velox/connectors/clp/search_lib/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/velox/connectors/clp/search_lib/CMakeLists.txt b/velox/connectors/clp/search_lib/CMakeLists.txt index aaf3a40d466..7f163d0aa2a 100644 --- a/velox/connectors/clp/search_lib/CMakeLists.txt +++ b/velox/connectors/clp/search_lib/CMakeLists.txt @@ -32,4 +32,3 @@ velox_link_libraries( clp_s::search::kql velox_vector) target_compile_features(clp-s-search PRIVATE cxx_std_20) - From a484bfdd19500c4d9efbc7823ed317cb6ff7bb8a Mon Sep 17 00:00:00 2001 From: dgibson Date: Thu, 10 Jul 2025 20:19:20 +0000 Subject: [PATCH 03/15] Marshal TIMESTAMP in connector test; make sure example archives are compressed using --timestamp-key timestamp. --- .../connectors/clp/tests/ClpConnectorTest.cpp | 90 ++++++++++-------- .../connectors/clp/tests/examples/test_2.clps | Bin 1947 -> 1943 bytes 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/velox/connectors/clp/tests/ClpConnectorTest.cpp b/velox/connectors/clp/tests/ClpConnectorTest.cpp index bb351984b64..5bcd3998ba2 100644 --- a/velox/connectors/clp/tests/ClpConnectorTest.cpp +++ b/velox/connectors/clp/tests/ClpConnectorTest.cpp @@ -26,6 +26,8 @@ #include "velox/exec/tests/utils/AssertQueryBuilder.h" #include "velox/exec/tests/utils/OperatorTestBase.h" #include "velox/exec/tests/utils/PlanBuilder.h" +#include "velox/type/Timestamp.h" +#include "velox/type/Type.h" namespace { @@ -34,6 +36,10 @@ using namespace facebook::velox::connector::clp; using facebook::velox::exec::test::PlanBuilder; +// Epoch seconds and nanoseconds for the timestamp "2025-04-30T08:50:05Z" +constexpr int64_t kTestTimestampSeconds{1746003005}; +constexpr uint64_t kTestTimestampNanoseconds{0ULL}; + class ClpConnectorTest : public exec::test::OperatorTestBase { public: const std::string kClpConnectorId = "test-clp"; @@ -165,7 +171,7 @@ TEST_F(ClpConnectorTest, test2NoPushdown) { .startTableScan() .outputType( ROW({"timestamp", "event"}, - {VARCHAR(), + {TIMESTAMP(), ROW({"type", "subtype", "severity"}, {VARCHAR(), VARCHAR(), VARCHAR()})})) .tableHandle(std::make_shared( @@ -173,7 +179,7 @@ TEST_F(ClpConnectorTest, test2NoPushdown) { .assignments( {{"timestamp", std::make_shared( - "timestamp", "timestamp", VARCHAR(), true)}, + "timestamp", "timestamp", TIMESTAMP(), true)}, {"event", std::make_shared( "event", @@ -190,18 +196,19 @@ TEST_F(ClpConnectorTest, test2NoPushdown) { auto output = getResults(plan, {makeClpSplit(getExampleFilePath("test_2.clps"))}); - auto expected = - makeRowVector({// timestamp - makeFlatVector({"2025-04-30T08:50:05Z"}), - // event - makeRowVector({ - // event.type - makeFlatVector({"storage"}), - // event.subtype - makeFlatVector({"disk_usage"}), - // event.severity - makeFlatVector({"WARNING"}), - })}); + auto expected = makeRowVector( + {// timestamp + makeFlatVector( + {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), + // event + makeRowVector({ + // event.type + makeFlatVector({"storage"}), + // event.subtype + makeFlatVector({"disk_usage"}), + // event.severity + makeFlatVector({"WARNING"}), + })}); test::assertEqualVectors(expected, output); } @@ -211,7 +218,7 @@ TEST_F(ClpConnectorTest, test2Pushdown) { .startTableScan() .outputType( ROW({"timestamp", "event"}, - {VARCHAR(), + {TIMESTAMP(), ROW({"type", "subtype", "severity"}, {VARCHAR(), VARCHAR(), VARCHAR()})})) .tableHandle(std::make_shared( @@ -224,7 +231,7 @@ TEST_F(ClpConnectorTest, test2Pushdown) { .assignments( {{"timestamp", std::make_shared( - "timestamp", "timestamp", VARCHAR(), true)}, + "timestamp", "timestamp", TIMESTAMP(), true)}, {"event", std::make_shared( "event", @@ -237,18 +244,19 @@ TEST_F(ClpConnectorTest, test2Pushdown) { auto output = getResults(plan, {makeClpSplit(getExampleFilePath("test_2.clps"))}); - auto expected = - makeRowVector({// timestamp - makeFlatVector({"2025-04-30T08:50:05Z"}), - // event - makeRowVector({ - // event.type - makeFlatVector({"storage"}), - // event.subtype - makeFlatVector({"disk_usage"}), - // event.severity - makeFlatVector({"WARNING"}), - })}); + auto expected = makeRowVector( + {// timestamp + makeFlatVector( + {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), + // event + makeRowVector({ + // event.type + makeFlatVector({"storage"}), + // event.subtype + makeFlatVector({"disk_usage"}), + // event.severity + makeFlatVector({"WARNING"}), + })}); test::assertEqualVectors(expected, output); } @@ -258,7 +266,7 @@ TEST_F(ClpConnectorTest, test2Hybrid) { .startTableScan() .outputType( ROW({"timestamp", "event"}, - {VARCHAR(), + {TIMESTAMP(), ROW({"type", "subtype", "severity", "tags"}, {VARCHAR(), VARCHAR(), VARCHAR(), ARRAY(VARCHAR())})})) .tableHandle(std::make_shared( @@ -270,7 +278,7 @@ TEST_F(ClpConnectorTest, test2Hybrid) { .assignments( {{"timestamp", std::make_shared( - "timestamp", "timestamp", VARCHAR(), true)}, + "timestamp", "timestamp", TIMESTAMP(), true)}, {"event", std::make_shared( "event", @@ -286,17 +294,19 @@ TEST_F(ClpConnectorTest, test2Hybrid) { getResults(plan, {makeClpSplit(getExampleFilePath("test_2.clps"))}); auto expected = makeRowVector( {// timestamp - makeFlatVector({"2025-04-30T08:50:05Z"}), + makeFlatVector( + {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), // event - makeRowVector({// event.type - makeFlatVector({"storage"}), - // event.subtype - makeFlatVector({"disk_usage"}), - // event.severity - makeFlatVector({"WARNING"}), - // event.tags - makeArrayVector( - {{"\"filesystem\"", "\"monitoring\""}})}) + makeRowVector( + {// event.type + makeFlatVector({"storage"}), + // event.subtype + makeFlatVector({"disk_usage"}), + // event.severity + makeFlatVector({"WARNING"}), + // event.tags + makeArrayVector( + {{"\"filesystem\"", "\"monitoring\""}})}) }); test::assertEqualVectors(expected, output); diff --git a/velox/connectors/clp/tests/examples/test_2.clps b/velox/connectors/clp/tests/examples/test_2.clps index ad773162d3af70c22fe438bbaa4342120afecb2a..22ddd92bb5bec8878349b71843b59e0229ec8aa5 100644 GIT binary patch delta 1137 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 Date: Fri, 11 Jul 2025 00:27:36 +0000 Subject: [PATCH 04/15] Fix test formatting --- .../connectors/clp/tests/ClpConnectorTest.cpp | 71 +++++++++---------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/velox/connectors/clp/tests/ClpConnectorTest.cpp b/velox/connectors/clp/tests/ClpConnectorTest.cpp index 5bcd3998ba2..805eefa62c6 100644 --- a/velox/connectors/clp/tests/ClpConnectorTest.cpp +++ b/velox/connectors/clp/tests/ClpConnectorTest.cpp @@ -196,19 +196,19 @@ TEST_F(ClpConnectorTest, test2NoPushdown) { auto output = getResults(plan, {makeClpSplit(getExampleFilePath("test_2.clps"))}); - auto expected = makeRowVector( - {// timestamp - makeFlatVector( - {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), - // event - makeRowVector({ - // event.type - makeFlatVector({"storage"}), - // event.subtype - makeFlatVector({"disk_usage"}), - // event.severity - makeFlatVector({"WARNING"}), - })}); + auto expected = + makeRowVector({// timestamp + makeFlatVector({Timestamp( + kTestTimestampSeconds, kTestTimestampNanoseconds)}), + // event + makeRowVector({ + // event.type + makeFlatVector({"storage"}), + // event.subtype + makeFlatVector({"disk_usage"}), + // event.severity + makeFlatVector({"WARNING"}), + })}); test::assertEqualVectors(expected, output); } @@ -244,19 +244,19 @@ TEST_F(ClpConnectorTest, test2Pushdown) { auto output = getResults(plan, {makeClpSplit(getExampleFilePath("test_2.clps"))}); - auto expected = makeRowVector( - {// timestamp - makeFlatVector( - {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), - // event - makeRowVector({ - // event.type - makeFlatVector({"storage"}), - // event.subtype - makeFlatVector({"disk_usage"}), - // event.severity - makeFlatVector({"WARNING"}), - })}); + auto expected = + makeRowVector({// timestamp + makeFlatVector({Timestamp( + kTestTimestampSeconds, kTestTimestampNanoseconds)}), + // event + makeRowVector({ + // event.type + makeFlatVector({"storage"}), + // event.subtype + makeFlatVector({"disk_usage"}), + // event.severity + makeFlatVector({"WARNING"}), + })}); test::assertEqualVectors(expected, output); } @@ -297,16 +297,15 @@ TEST_F(ClpConnectorTest, test2Hybrid) { makeFlatVector( {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), // event - makeRowVector( - {// event.type - makeFlatVector({"storage"}), - // event.subtype - makeFlatVector({"disk_usage"}), - // event.severity - makeFlatVector({"WARNING"}), - // event.tags - makeArrayVector( - {{"\"filesystem\"", "\"monitoring\""}})}) + makeRowVector({// event.type + makeFlatVector({"storage"}), + // event.subtype + makeFlatVector({"disk_usage"}), + // event.severity + makeFlatVector({"WARNING"}), + // event.tags + makeArrayVector( + {{"\"filesystem\"", "\"monitoring\""}})}) }); test::assertEqualVectors(expected, output); From 6c0c5557976e8b74bdf580a33abc40d28abf4969 Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 00:27:50 +0000 Subject: [PATCH 05/15] Address rabbit comments --- velox/connectors/clp/search_lib/ClpCursor.cpp | 1 + velox/connectors/clp/search_lib/ClpVectorLoader.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/velox/connectors/clp/search_lib/ClpCursor.cpp b/velox/connectors/clp/search_lib/ClpCursor.cpp index 364929dd144..fa6d67bf22b 100644 --- a/velox/connectors/clp/search_lib/ClpCursor.cpp +++ b/velox/connectors/clp/search_lib/ClpCursor.cpp @@ -217,6 +217,7 @@ ErrorCode ClpCursor::loadArchive() { columnDescriptor->set_matching_types( LiteralType::EpochDateT | LiteralType::IntegerT | LiteralType::FloatT); + break; default: break; } diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp index a310f52b057..15cbc272fe3 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp @@ -52,7 +52,7 @@ template auto estimatePrecision(T timestamp) -> TimestampPrecision { constexpr int64_t kEpochMilliseconds1971{31536000000}; constexpr int64_t kEpochMicroseconds1971{31536000000000}; - constexpr int64_t kEpochNanoseconds1971{31536000000000}; + constexpr int64_t kEpochNanoseconds1971{31536000000000000}; if (timestamp > kEpochNanoseconds1971) { return TimestampPrecision::Nanoseconds; } else if (timestamp > kEpochMicroseconds1971) { @@ -84,7 +84,7 @@ auto convertToVeloxTimestamp(double timestamp) -> Timestamp { case TimestampPrecision::Seconds: break; } - double seconds{floor(timestamp)}; + double seconds{std::floor(timestamp)}; double nanoseconds{(timestamp - seconds) * Timestamp::kNanosInSecond}; return Timestamp( static_cast(seconds), static_cast(nanoseconds)); From bebe575a9b195b631c80bffdc47e19f176a1874d Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 15:25:34 +0000 Subject: [PATCH 06/15] Improve comment on heuristic. --- velox/connectors/clp/search_lib/ClpVectorLoader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp index 15cbc272fe3..4c28310c5a5 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp @@ -38,13 +38,17 @@ enum class TimestampPrecision : uint8_t { /** * Estimates the precision of an epoch timestamp as seconds, milliseconds, - * or nanoseconds. + * microseconds, or nanoseconds. * * This heuristic relies on the fact that 1 year of epoch nanoseconds is * approximately 1000 years of epoch microseconds and so on. This heuristic * can be unreliable for timestamps sufficiently close to the epoch, but should * otherwise be accurate for the next 1000 years. * + * Note: Future versions of the clp-s archive format will adopt a nanosecond-precision integer + * timestamp format (as opposed to the current format which allows other precisions), at which point + * we can remove this heuristic. + * * @param timestamp * @return the estimated timestamp precision */ From d8fd72aec5a09d32202cdc730064c962e6262802 Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 15:26:59 +0000 Subject: [PATCH 07/15] Alphabetize clp_s::ColumnType. --- velox/connectors/clp/search_lib/ClpCursor.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/velox/connectors/clp/search_lib/ClpCursor.h b/velox/connectors/clp/search_lib/ClpCursor.h index 81c224f5e0f..f6303a2ef94 100644 --- a/velox/connectors/clp/search_lib/ClpCursor.h +++ b/velox/connectors/clp/search_lib/ClpCursor.h @@ -50,11 +50,11 @@ enum class ErrorCode { }; enum class ColumnType { - String, - Integer, - Float, Array, Boolean, + Float, + Integer, + String, Timestamp, Unknown = -1 }; From d50ba133f628a3f2cf5e8f328e4a0d23b8fcee11 Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 15:33:10 +0000 Subject: [PATCH 08/15] Fix formatting --- velox/connectors/clp/search_lib/ClpVectorLoader.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp index 4c28310c5a5..1cd4f0c2366 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp @@ -45,10 +45,11 @@ enum class TimestampPrecision : uint8_t { * can be unreliable for timestamps sufficiently close to the epoch, but should * otherwise be accurate for the next 1000 years. * - * Note: Future versions of the clp-s archive format will adopt a nanosecond-precision integer - * timestamp format (as opposed to the current format which allows other precisions), at which point - * we can remove this heuristic. - * + * Note: Future versions of the clp-s archive format will adopt a + * nanosecond-precision integer timestamp format (as opposed to the current + * format which allows other precisions), at which point we can remove this + * heuristic. + * * @param timestamp * @return the estimated timestamp precision */ From 011741ac308a4962453611d171d2614d876f23b1 Mon Sep 17 00:00:00 2001 From: Devin Gibson Date: Fri, 11 Jul 2025 13:49:28 -0400 Subject: [PATCH 09/15] Apply suggestions from code review Co-authored-by: Xiaochong(Eddy) Wei <40865608+anlowee@users.noreply.github.com> --- .../clp/search_lib/ClpVectorLoader.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp index 1cd4f0c2366..c8c64ee8c0a 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp @@ -29,6 +29,7 @@ namespace facebook::velox::connector::clp::search_lib { namespace { + enum class TimestampPrecision : uint8_t { Seconds, Milliseconds, @@ -58,20 +59,16 @@ auto estimatePrecision(T timestamp) -> TimestampPrecision { constexpr int64_t kEpochMilliseconds1971{31536000000}; constexpr int64_t kEpochMicroseconds1971{31536000000000}; constexpr int64_t kEpochNanoseconds1971{31536000000000000}; - if (timestamp > kEpochNanoseconds1971) { + auto absTimestamp = timestamp >= 0 ? timestamp : -timestamp; + + if (absTimestamp > kEpochNanoseconds1971) { return TimestampPrecision::Nanoseconds; - } else if (timestamp > kEpochMicroseconds1971) { + } else if (absTimestamp > kEpochMicroseconds1971) { return TimestampPrecision::Microseconds; - } else if (timestamp > kEpochMilliseconds1971) { - return TimestampPrecision::Milliseconds; - } else if (timestamp > -kEpochMilliseconds1971) { - return TimestampPrecision::Seconds; - } else if (timestamp > -kEpochMicroseconds1971) { + } else if (absTimestamp > kEpochMilliseconds1971) { return TimestampPrecision::Milliseconds; - } else if (timestamp > -kEpochNanoseconds1971) { - return TimestampPrecision::Microseconds; } else { - return TimestampPrecision::Nanoseconds; + return TimestampPrecision::Seconds; } } @@ -117,6 +114,7 @@ auto convertToVeloxTimestamp(int64_t timestamp) -> Timestamp { } return Timestamp(seconds, static_cast(nanoseconds)); } + } // namespace ClpVectorLoader::ClpVectorLoader( From 60b8ef4070029d111d06a3f363335e24de4fd6a8 Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 13:52:29 -0400 Subject: [PATCH 10/15] Update multi-line comment to follow velox style. --- .../clp/search_lib/ClpVectorLoader.cpp | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp index c8c64ee8c0a..c31be9d7a4b 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp @@ -37,23 +37,21 @@ enum class TimestampPrecision : uint8_t { Nanoseconds }; -/** - * Estimates the precision of an epoch timestamp as seconds, milliseconds, - * microseconds, or nanoseconds. - * - * This heuristic relies on the fact that 1 year of epoch nanoseconds is - * approximately 1000 years of epoch microseconds and so on. This heuristic - * can be unreliable for timestamps sufficiently close to the epoch, but should - * otherwise be accurate for the next 1000 years. - * - * Note: Future versions of the clp-s archive format will adopt a - * nanosecond-precision integer timestamp format (as opposed to the current - * format which allows other precisions), at which point we can remove this - * heuristic. - * - * @param timestamp - * @return the estimated timestamp precision - */ +/// Estimates the precision of an epoch timestamp as seconds, milliseconds, +/// microseconds, or nanoseconds. +/// +/// This heuristic relies on the fact that 1 year of epoch nanoseconds is +/// approximately 1000 years of epoch microseconds and so on. This heuristic +/// can be unreliable for timestamps sufficiently close to the epoch, but +/// should otherwise be accurate for the next 1000 years. +/// +/// Note: Future versions of the clp-s archive format will adopt a +/// nanosecond-precision integer timestamp format (as opposed to the current +/// format which allows other precisions), at which point we can remove this +/// heuristic. +/// +/// @param timestamp +/// @return the estimated timestamp precision template auto estimatePrecision(T timestamp) -> TimestampPrecision { constexpr int64_t kEpochMilliseconds1971{31536000000}; From 8063aac0f8dc753490f41ecdedd2b19cd305dfbf Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 18:15:04 +0000 Subject: [PATCH 11/15] Add test to exercise various timestamp marshalling code-paths. --- .../connectors/clp/tests/ClpConnectorTest.cpp | 26 ++++++++++++++++++ .../connectors/clp/tests/examples/test_3.clps | Bin 0 -> 674 bytes .../clp/tests/examples/test_3.ndjson | 4 +++ 3 files changed, 30 insertions(+) create mode 100644 velox/connectors/clp/tests/examples/test_3.clps create mode 100644 velox/connectors/clp/tests/examples/test_3.ndjson diff --git a/velox/connectors/clp/tests/ClpConnectorTest.cpp b/velox/connectors/clp/tests/ClpConnectorTest.cpp index 805eefa62c6..de9d4f470a0 100644 --- a/velox/connectors/clp/tests/ClpConnectorTest.cpp +++ b/velox/connectors/clp/tests/ClpConnectorTest.cpp @@ -311,6 +311,32 @@ TEST_F(ClpConnectorTest, test2Hybrid) { test::assertEqualVectors(expected, output); } +TEST_F(ClpConnectorTest, test3TimestampMarshalling) { + auto plan = + PlanBuilder(pool_.get()) + .startTableScan() + .outputType(ROW({"timestamp"}, {TIMESTAMP()})) + .tableHandle(std::make_shared( + kClpConnectorId, + "test_3", + nullptr)) + .assignments( + {{"timestamp", + std::make_shared( + "timestamp", "timestamp", TIMESTAMP(), true)}}) + .endTableScan() + .planNode(); + + auto output = + getResults(plan, {makeClpSplit(getExampleFilePath("test_3.clps"))}); + auto expected = makeRowVector( + {// timestamp + makeFlatVector( + {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds),Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds),Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds),Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), + }); + test::assertEqualVectors(expected, output); +} + } // namespace int main(int argc, char** argv) { diff --git a/velox/connectors/clp/tests/examples/test_3.clps b/velox/connectors/clp/tests/examples/test_3.clps new file mode 100644 index 0000000000000000000000000000000000000000..3dd9f37b4ef296706f39de518798f9e921e6d3fb GIT binary patch literal 674 zcmeyXf7F19ftjI`0Rk2=K^X+7B1VV;jjj5B86teS8QQ`EEDbWVq#GJb5*NReIcAvo z^w-N!=DG17bjzkkKY8~1zGhMFjpv8|+4T5_T>fpyYb2~4-moj=?W2qSjJ6CeK**Q! zec4@J(F6*JCYO^vXqa#+`*pO)iHS`C8e#xP+b?KIAQrFDO5GSN7cntt&rYUpe=H zr`-I)1chDJkHl{5HGSaF^YD1lN~Vi#l?;9CJc$gil$sp?lQ> z7pK^(@gY-vl~krJap-wc^CRnr#lGujypMcv{E!m;>#gI1cY-q4SR@TX8GJ;$J00e2 z-z%xCd!*{;%CLveVz2$&dO4#+GG6xnEot-V`;Mi`$`@~BNY6jE%+>1q*SMI5i{TlL zee$a%e}7pL#mCQZQY26F=ZCXt40#G-LLE#UOoy8rAG%q1t>+A9kXl;lEoJx}65_l} z3{RNY82$qR0~aVNco}l?)8kXiQu9jUGgB(KSwRuWS(2HXT3nKtTfo7{z|QbM*wUUU za-m3gg2aTc3>zROy=7p?U}j(f#V0chE0APkXgJ{WIPcSjNu|?ovfYBHQe|W)U}W$B zrW7Ux21W)821ZT>`(6fSHX&vS#{Sr{#-_%e)CQ1ttN>!jR7M6BCMKYEhm(&PejBqf pFesg>tmd(nVDRXB+&Ybc!GXV$<(4BWL$G9n$VJDvga?cXi~t{{^!)$; literal 0 HcmV?d00001 diff --git a/velox/connectors/clp/tests/examples/test_3.ndjson b/velox/connectors/clp/tests/examples/test_3.ndjson new file mode 100644 index 00000000000..0839ab1263b --- /dev/null +++ b/velox/connectors/clp/tests/examples/test_3.ndjson @@ -0,0 +1,4 @@ +{"timestamp": "2025-04-30T08:50:05.000Z"} +{"timestamp": 1746003005.0} +{"timestamp": 1746003005000000} +{"timestamp": 1746003005000000000} From 1ad0204e672a5fd005cc9385d66e300606ffe96d Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 18:19:15 +0000 Subject: [PATCH 12/15] Code format --- .../connectors/clp/tests/ClpConnectorTest.cpp | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/velox/connectors/clp/tests/ClpConnectorTest.cpp b/velox/connectors/clp/tests/ClpConnectorTest.cpp index de9d4f470a0..a02b027c137 100644 --- a/velox/connectors/clp/tests/ClpConnectorTest.cpp +++ b/velox/connectors/clp/tests/ClpConnectorTest.cpp @@ -312,28 +312,29 @@ TEST_F(ClpConnectorTest, test2Hybrid) { } TEST_F(ClpConnectorTest, test3TimestampMarshalling) { - auto plan = - PlanBuilder(pool_.get()) - .startTableScan() - .outputType(ROW({"timestamp"}, {TIMESTAMP()})) - .tableHandle(std::make_shared( - kClpConnectorId, - "test_3", - nullptr)) - .assignments( - {{"timestamp", - std::make_shared( - "timestamp", "timestamp", TIMESTAMP(), true)}}) - .endTableScan() - .planNode(); + auto plan = PlanBuilder(pool_.get()) + .startTableScan() + .outputType(ROW({"timestamp"}, {TIMESTAMP()})) + .tableHandle( + std::make_shared( + kClpConnectorId, "test_3", nullptr)) + .assignments( + {{"timestamp", + std::make_shared( + "timestamp", "timestamp", TIMESTAMP(), true)}}) + .endTableScan() + .planNode(); auto output = getResults(plan, {makeClpSplit(getExampleFilePath("test_3.clps"))}); - auto expected = makeRowVector( - {// timestamp - makeFlatVector( - {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds),Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds),Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds),Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), - }); + auto expected = makeRowVector({ + // timestamp + makeFlatVector( + {Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds), + Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds), + Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds), + Timestamp(kTestTimestampSeconds, kTestTimestampNanoseconds)}), + }); test::assertEqualVectors(expected, output); } From 9e47c53cf09de6b66b809b014a7f82324a4c588a Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 18:20:51 +0000 Subject: [PATCH 13/15] Code formatting --- velox/connectors/clp/tests/ClpConnectorTest.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/velox/connectors/clp/tests/ClpConnectorTest.cpp b/velox/connectors/clp/tests/ClpConnectorTest.cpp index a02b027c137..cea13f119f2 100644 --- a/velox/connectors/clp/tests/ClpConnectorTest.cpp +++ b/velox/connectors/clp/tests/ClpConnectorTest.cpp @@ -315,9 +315,8 @@ TEST_F(ClpConnectorTest, test3TimestampMarshalling) { auto plan = PlanBuilder(pool_.get()) .startTableScan() .outputType(ROW({"timestamp"}, {TIMESTAMP()})) - .tableHandle( - std::make_shared( - kClpConnectorId, "test_3", nullptr)) + .tableHandle(std::make_shared( + kClpConnectorId, "test_3", nullptr)) .assignments( {{"timestamp", std::make_shared( From 8581c75ac3af7311b0c67b02d437ac677c92f208 Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 20:05:20 +0000 Subject: [PATCH 14/15] Modify timestamp conversion to avoid overflow --- .../clp/search_lib/ClpVectorLoader.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp index c31be9d7a4b..86661597940 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp @@ -91,21 +91,27 @@ auto convertToVeloxTimestamp(double timestamp) -> Timestamp { } auto convertToVeloxTimestamp(int64_t timestamp) -> Timestamp { + int64_t precisionDifference{Timestamp::kNanosInSecond}; switch (estimatePrecision(timestamp)) { case TimestampPrecision::Nanoseconds: break; case TimestampPrecision::Microseconds: - timestamp *= Timestamp::kNanosecondsInMicrosecond; + nanosecondPrecisionDifference = + Timestamp::kNanosInSecond / Timestamp::kNanosecondsInMicrosecond; break; case TimestampPrecision::Milliseconds: - timestamp *= Timestamp::kNanosecondsInMillisecond; + nanosecondPrecisionDifference = + Timestamp::kNanosInSecond / Timestamp::kNanosecondsInMillisecond; break; case TimestampPrecision::Seconds: - timestamp *= Timestamp::kNanosInSecond; + precisionDifference = + Timestamp::kNanosInSecond / Timestamp::kNanosInSecond; break; } - int64_t seconds{timestamp / Timestamp::kNanosInSecond}; - int64_t nanoseconds{timestamp - seconds * Timestamp::kNanosInSecond}; + int64_t seconds{timestamp / precisionDifference}; + int64_t nanoseconds{ + (timestamp % precisionDifference) * + (Timestamp::kNanosInSecond / precisionDifference)}; if (nanoseconds < 0) { seconds -= 1; nanoseconds += Timestamp::kNanosInSecond; From 801e1183b01443dc800970037637f7f878fcd898 Mon Sep 17 00:00:00 2001 From: dgibson Date: Fri, 11 Jul 2025 20:09:51 +0000 Subject: [PATCH 15/15] Fix compilation issue --- velox/connectors/clp/search_lib/ClpVectorLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp index 86661597940..6bd58e8a2a2 100644 --- a/velox/connectors/clp/search_lib/ClpVectorLoader.cpp +++ b/velox/connectors/clp/search_lib/ClpVectorLoader.cpp @@ -96,11 +96,11 @@ auto convertToVeloxTimestamp(int64_t timestamp) -> Timestamp { case TimestampPrecision::Nanoseconds: break; case TimestampPrecision::Microseconds: - nanosecondPrecisionDifference = + precisionDifference = Timestamp::kNanosInSecond / Timestamp::kNanosecondsInMicrosecond; break; case TimestampPrecision::Milliseconds: - nanosecondPrecisionDifference = + precisionDifference = Timestamp::kNanosInSecond / Timestamp::kNanosecondsInMillisecond; break; case TimestampPrecision::Seconds: