From f32352c58f16b9545fec0f31c54bddbf20fde1c6 Mon Sep 17 00:00:00 2001 From: glywk Date: Sat, 27 Jul 2024 17:18:55 +0200 Subject: [PATCH 1/4] [C++] Add local-timestamp-millis, local-timestamp-micros logical types as defined since specification 1.10.0 --- lang/c++/impl/Compiler.cc | 4 ++++ lang/c++/impl/LogicalType.cc | 6 ++++++ lang/c++/impl/Node.cc | 13 +++++++++++++ lang/c++/include/avro/LogicalType.hh | 2 ++ lang/c++/test/SchemaTests.cc | 28 ++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+) diff --git a/lang/c++/impl/Compiler.cc b/lang/c++/impl/Compiler.cc index 3b287c9eeb0..2599f7cc664 100644 --- a/lang/c++/impl/Compiler.cc +++ b/lang/c++/impl/Compiler.cc @@ -369,6 +369,10 @@ 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 == "local-timestamp-millis") + t = LogicalType::LOCAL_TIMESTAMP_MILLIS; + else if (typeField == "local-timestamp-micros") + t = LogicalType::LOCAL_TIMESTAMP_MICROS; 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 5e03a313d8f..a7260accd16 100644 --- a/lang/c++/impl/LogicalType.cc +++ b/lang/c++/impl/LogicalType.cc @@ -71,6 +71,12 @@ void LogicalType::printJson(std::ostream &os) const { case TIMESTAMP_MICROS: os << R"("logicalType": "timestamp-micros")"; break; + case LOCAL_TIMESTAMP_MILLIS: + os << R"("logicalType": "local-timestamp-millis")"; + break; + case LOCAL_TIMESTAMP_MICROS: + os << R"("logicalType": "local-timestamp-micros")"; + break; case DURATION: os << R"("logicalType": "duration")"; break; diff --git a/lang/c++/impl/Node.cc b/lang/c++/impl/Node.cc index 14ce6ecf05b..0e1d025ad2f 100644 --- a/lang/c++/impl/Node.cc +++ b/lang/c++/impl/Node.cc @@ -18,6 +18,7 @@ #include #include +#include #include "Node.hh" @@ -189,6 +190,18 @@ void Node::setLogicalType(LogicalType logicalType) { "LONG type"); } break; + case LogicalType::LOCAL_TIMESTAMP_MILLIS: + if (type_ != AVRO_LONG) { + throw Exception("LOCAL_TIMESTAMP-MILLIS logical type can only annotate " + "LONG type"); + } + break; + case LogicalType::LOCAL_TIMESTAMP_MICROS: + if (type_ != AVRO_LONG) { + throw Exception("LOCAL_TIMESTAMP-MICROS 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 ff430fd086a..3156f164e1f 100644 --- a/lang/c++/include/avro/LogicalType.hh +++ b/lang/c++/include/avro/LogicalType.hh @@ -35,6 +35,8 @@ public: TIME_MICROS, TIMESTAMP_MILLIS, TIMESTAMP_MICROS, + LOCAL_TIMESTAMP_MILLIS, + LOCAL_TIMESTAMP_MICROS, DURATION, UUID }; diff --git a/lang/c++/test/SchemaTests.cc b/lang/c++/test/SchemaTests.cc index 543f9e05087..f57cfd1352b 100644 --- a/lang/c++/test/SchemaTests.cc +++ b/lang/c++/test/SchemaTests.cc @@ -217,6 +217,8 @@ 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":"local-timestamp-millis"})", + R"({"type":"long","logicalType":"local-timestamp-micros"})", R"({"type":"fixed","name":"test","size":12,"logicalType":"duration"})", R"({"type":"string","logicalType":"uuid"})", @@ -242,6 +244,8 @@ 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":"local-timestamp-millis"})", + R"({"type":"string","logicalType":"local-timestamp-micros"})", R"({"type":"string","logicalType":"duration"})", R"({"type":"long","logicalType":"uuid"})", // Missing the required field 'precision'. @@ -356,6 +360,12 @@ static void testLogicalTypes() { const char *timestampMicrosType = "{\n\ \"type\": \"long\", \"logicalType\": \"timestamp-micros\"\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 *durationType = "{\n\ \"type\": \"fixed\",\n\ \"size\": 12,\n\ @@ -436,6 +446,24 @@ static void testLogicalTypes() { GenericDatum datum(schema); BOOST_CHECK(datum.logicalType().type() == LogicalType::TIMESTAMP_MICROS); } + { + BOOST_TEST_CHECKPOINT(localTimestampMillisType); + ValidSchema schema = compileJsonSchemaFromString(localTimestampMillisType); + BOOST_CHECK(schema.root()->type() == AVRO_LONG); + LogicalType logicalType = schema.root()->logicalType(); + BOOST_CHECK(logicalType.type() == LogicalType::LOCAL_TIMESTAMP_MILLIS); + GenericDatum datum(schema); + BOOST_CHECK(datum.logicalType().type() == LogicalType::LOCAL_TIMESTAMP_MILLIS); + } + { + BOOST_TEST_CHECKPOINT(localTimestampMicrosType); + ValidSchema schema = compileJsonSchemaFromString(localTimestampMicrosType); + BOOST_CHECK(schema.root()->type() == AVRO_LONG); + LogicalType logicalType = schema.root()->logicalType(); + BOOST_CHECK(logicalType.type() == LogicalType::LOCAL_TIMESTAMP_MICROS); + GenericDatum datum(schema); + BOOST_CHECK(datum.logicalType().type() == LogicalType::LOCAL_TIMESTAMP_MICROS); + } { BOOST_TEST_CHECKPOINT(durationType); ValidSchema schema = compileJsonSchemaFromString(durationType); From 2f22749a8ee3f475ede0fc07aa92fe94c541641b Mon Sep 17 00:00:00 2001 From: glywk Date: Tue, 30 Jul 2024 19:17:27 +0200 Subject: [PATCH 2/4] Align exception comment on logical type names Co-authored-by: Kalle Olavi Niemitalo --- lang/c++/impl/Node.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/c++/impl/Node.cc b/lang/c++/impl/Node.cc index 0e1d025ad2f..e7a3d6301b2 100644 --- a/lang/c++/impl/Node.cc +++ b/lang/c++/impl/Node.cc @@ -192,7 +192,7 @@ void Node::setLogicalType(LogicalType logicalType) { break; case LogicalType::LOCAL_TIMESTAMP_MILLIS: if (type_ != AVRO_LONG) { - throw Exception("LOCAL_TIMESTAMP-MILLIS logical type can only annotate " + throw Exception("LOCAL-TIMESTAMP-MILLIS logical type can only annotate " "LONG type"); } break; From 2334788c8b5eb8fc3b4a794f5af81e0714cb29d4 Mon Sep 17 00:00:00 2001 From: glywk Date: Mon, 5 Aug 2024 14:42:10 +0200 Subject: [PATCH 3/4] [C++] Fix local-timestamp-micros exception comment --- lang/c++/impl/Node.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/c++/impl/Node.cc b/lang/c++/impl/Node.cc index e7a3d6301b2..b39160f8597 100644 --- a/lang/c++/impl/Node.cc +++ b/lang/c++/impl/Node.cc @@ -198,7 +198,7 @@ void Node::setLogicalType(LogicalType logicalType) { break; case LogicalType::LOCAL_TIMESTAMP_MICROS: if (type_ != AVRO_LONG) { - throw Exception("LOCAL_TIMESTAMP-MICROS logical type can only annotate " + throw Exception("LOCAL-TIMESTAMP-MICROS logical type can only annotate " "LONG type"); } break; From c3c747e822a2a394c1386e1a98c45e196c9de019 Mon Sep 17 00:00:00 2001 From: glywk Date: Thu, 15 Aug 2024 22:18:11 +0200 Subject: [PATCH 4/4] [C++] Fix include vector dependency location --- lang/c++/impl/Node.cc | 1 - lang/c++/include/avro/Node.hh | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/c++/impl/Node.cc b/lang/c++/impl/Node.cc index b39160f8597..9f641e2956a 100644 --- a/lang/c++/impl/Node.cc +++ b/lang/c++/impl/Node.cc @@ -18,7 +18,6 @@ #include #include -#include #include "Node.hh" diff --git a/lang/c++/include/avro/Node.hh b/lang/c++/include/avro/Node.hh index f76078b052b..e1a8e660f4d 100644 --- a/lang/c++/include/avro/Node.hh +++ b/lang/c++/include/avro/Node.hh @@ -25,6 +25,7 @@ #include #include #include +#include #include "CustomAttributes.hh" #include "Exception.hh"