From f229a5c31ae5199f7a6b506d51e0f469e0d730a0 Mon Sep 17 00:00:00 2001 From: glywk Date: Sat, 17 Aug 2024 23:54:02 +0200 Subject: [PATCH 1/2] AVRO-4038: [C++] Add local-timestamp-nanos and timestamp-nanos --- lang/c++/impl/Compiler.cc | 4 ++++ lang/c++/impl/LogicalType.cc | 6 ++++++ lang/c++/impl/Node.cc | 12 ++++++++++++ lang/c++/include/avro/LogicalType.hh | 2 ++ lang/c++/test/SchemaTests.cc | 28 ++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+) diff --git a/lang/c++/impl/Compiler.cc b/lang/c++/impl/Compiler.cc index 2599f7cc664..f3c2397da24 100644 --- a/lang/c++/impl/Compiler.cc +++ b/lang/c++/impl/Compiler.cc @@ -369,10 +369,14 @@ static LogicalType makeLogicalType(const Entity &e, const Object &m) { t = LogicalType::TIMESTAMP_MILLIS; else if (typeField == "timestamp-micros") t = LogicalType::TIMESTAMP_MICROS; + else if (typeField == "timestamp-nanos") + t = LogicalType::TIMESTAMP_NANOS; else if (typeField == "local-timestamp-millis") t = LogicalType::LOCAL_TIMESTAMP_MILLIS; else if (typeField == "local-timestamp-micros") t = LogicalType::LOCAL_TIMESTAMP_MICROS; + else if (typeField == "local-timestamp-nanos") + t = LogicalType::LOCAL_TIMESTAMP_NANOS; else if (typeField == "duration") t = LogicalType::DURATION; else if (typeField == "uuid") diff --git a/lang/c++/impl/LogicalType.cc b/lang/c++/impl/LogicalType.cc index a7260accd16..ed6a12f0892 100644 --- a/lang/c++/impl/LogicalType.cc +++ b/lang/c++/impl/LogicalType.cc @@ -71,12 +71,18 @@ void LogicalType::printJson(std::ostream &os) const { case TIMESTAMP_MICROS: os << R"("logicalType": "timestamp-micros")"; break; + case TIMESTAMP_NANOS: + os << R"("logicalType": "timestamp-nanos")"; + break; case LOCAL_TIMESTAMP_MILLIS: os << R"("logicalType": "local-timestamp-millis")"; break; case LOCAL_TIMESTAMP_MICROS: os << R"("logicalType": "local-timestamp-micros")"; break; + case LOCAL_TIMESTAMP_NANOS: + os << R"("logicalType": "local-timestamp-nanos")"; + break; case DURATION: os << R"("logicalType": "duration")"; break; diff --git a/lang/c++/impl/Node.cc b/lang/c++/impl/Node.cc index 9f641e2956a..bde556bf314 100644 --- a/lang/c++/impl/Node.cc +++ b/lang/c++/impl/Node.cc @@ -189,6 +189,12 @@ void Node::setLogicalType(LogicalType logicalType) { "LONG type"); } break; + case LogicalType::TIMESTAMP_NANOS: + if (type_ != AVRO_LONG) { + throw Exception("TIMESTAMP-NANOS logical type can only annotate " + "LONG type"); + } + break; case LogicalType::LOCAL_TIMESTAMP_MILLIS: if (type_ != AVRO_LONG) { throw Exception("LOCAL-TIMESTAMP-MILLIS logical type can only annotate " @@ -201,6 +207,12 @@ void Node::setLogicalType(LogicalType logicalType) { "LONG type"); } break; + case LogicalType::LOCAL_TIMESTAMP_NANOS: + if (type_ != AVRO_LONG) { + throw Exception("LOCAL-TIMESTAMP-NANOS logical type can only annotate " + "LONG type"); + } + break; case LogicalType::DURATION: if (type_ != AVRO_FIXED || fixedSize() != 12) { throw Exception("DURATION logical type can only annotate " diff --git a/lang/c++/include/avro/LogicalType.hh b/lang/c++/include/avro/LogicalType.hh index 3156f164e1f..b2a7d0294ff 100644 --- a/lang/c++/include/avro/LogicalType.hh +++ b/lang/c++/include/avro/LogicalType.hh @@ -35,8 +35,10 @@ public: TIME_MICROS, TIMESTAMP_MILLIS, TIMESTAMP_MICROS, + TIMESTAMP_NANOS, LOCAL_TIMESTAMP_MILLIS, LOCAL_TIMESTAMP_MICROS, + LOCAL_TIMESTAMP_NANOS, DURATION, UUID }; diff --git a/lang/c++/test/SchemaTests.cc b/lang/c++/test/SchemaTests.cc index f57cfd1352b..029be79d57e 100644 --- a/lang/c++/test/SchemaTests.cc +++ b/lang/c++/test/SchemaTests.cc @@ -217,8 +217,10 @@ const char *roundTripSchemas[] = { R"({"type":"long","logicalType":"time-micros"})", R"({"type":"long","logicalType":"timestamp-millis"})", R"({"type":"long","logicalType":"timestamp-micros"})", + R"({"type":"long","logicalType":"timestamp-nanos"})", R"({"type":"long","logicalType":"local-timestamp-millis"})", R"({"type":"long","logicalType":"local-timestamp-micros"})", + R"({"type":"long","logicalType":"local-timestamp-nanos"})", R"({"type":"fixed","name":"test","size":12,"logicalType":"duration"})", R"({"type":"string","logicalType":"uuid"})", @@ -244,8 +246,10 @@ const char *malformedLogicalTypes[] = { R"({"type":"string","logicalType":"time-micros"})", R"({"type":"string","logicalType":"timestamp-millis"})", R"({"type":"string","logicalType":"timestamp-micros"})", + R"({"type":"string","logicalType":"timestamp-nanos"})", R"({"type":"string","logicalType":"local-timestamp-millis"})", R"({"type":"string","logicalType":"local-timestamp-micros"})", + R"({"type":"string","logicalType":"local-timestamp-nanos"})", R"({"type":"string","logicalType":"duration"})", R"({"type":"long","logicalType":"uuid"})", // Missing the required field 'precision'. @@ -360,12 +364,18 @@ static void testLogicalTypes() { const char *timestampMicrosType = "{\n\ \"type\": \"long\", \"logicalType\": \"timestamp-micros\"\n\ }"; + const char *timestampNanosType = "{\n\ + \"type\": \"long\", \"logicalType\": \"timestamp-nanos\"\n\ + }"; const char *localTimestampMillisType = "{\n\ \"type\": \"long\", \"logicalType\": \"local-timestamp-millis\"\n\ }"; const char *localTimestampMicrosType = "{\n\ \"type\": \"long\", \"logicalType\": \"local-timestamp-micros\"\n\ }"; + const char *localTimestampNanosType = "{\n\ + \"type\": \"long\", \"logicalType\": \"local-timestamp-nanos\"\n\ + }"; const char *durationType = "{\n\ \"type\": \"fixed\",\n\ \"size\": 12,\n\ @@ -446,6 +456,15 @@ static void testLogicalTypes() { GenericDatum datum(schema); BOOST_CHECK(datum.logicalType().type() == LogicalType::TIMESTAMP_MICROS); } + { + BOOST_TEST_CHECKPOINT(timestampNanosType); + ValidSchema schema = compileJsonSchemaFromString(timestampNanosType); + BOOST_CHECK(schema.root()->type() == AVRO_LONG); + LogicalType logicalType = schema.root()->logicalType(); + BOOST_CHECK(logicalType.type() == LogicalType::TIMESTAMP_NANOS); + GenericDatum datum(schema); + BOOST_CHECK(datum.logicalType().type() == LogicalType::TIMESTAMP_NANOS); + } { BOOST_TEST_CHECKPOINT(localTimestampMillisType); ValidSchema schema = compileJsonSchemaFromString(localTimestampMillisType); @@ -464,6 +483,15 @@ static void testLogicalTypes() { GenericDatum datum(schema); BOOST_CHECK(datum.logicalType().type() == LogicalType::LOCAL_TIMESTAMP_MICROS); } + { + BOOST_TEST_CHECKPOINT(localTimestampNanosType); + ValidSchema schema = compileJsonSchemaFromString(localTimestampNanosType); + BOOST_CHECK(schema.root()->type() == AVRO_LONG); + LogicalType logicalType = schema.root()->logicalType(); + BOOST_CHECK(logicalType.type() == LogicalType::LOCAL_TIMESTAMP_NANOS); + GenericDatum datum(schema); + BOOST_CHECK(datum.logicalType().type() == LogicalType::LOCAL_TIMESTAMP_NANOS); + } { BOOST_TEST_CHECKPOINT(durationType); ValidSchema schema = compileJsonSchemaFromString(durationType); From 1e985f98ebd42f8703718f4dc1b1542d0565aaaa Mon Sep 17 00:00:00 2001 From: Martin Tzvetanov Grigorov Date: Tue, 20 Aug 2024 09:39:12 +0300 Subject: [PATCH 2/2] Add "pull-requests: write" permission to the labeler Copied from the example at https://github.com/actions/labeler?tab=readme-ov-file#outputs Trying to fix https://github.com/apache/avro/actions/runs/10460767435/job/28981928566?pr=3102 ``` Run actions/labeler@v5 with: repo-token: *** sync-labels: true configuration-path: .github/labeler.yml dot: true The configuration file (path: .github/labeler.yml) was not found locally, fetching via the api Warning: The action requires write permission to add labels to pull requests. For more information please refer to the action documentation: https://github.com/actions/labeler#permissions Error: Resource not accessible by integration ``` Signed-off-by: Martin Tzvetanov Grigorov --- .github/workflows/labeler.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 815d5d02a5c..53280443d29 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -21,6 +21,9 @@ on: pull_request_target jobs: triage: + permissions: + contents: read + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/labeler@v5