Skip to content

Commit

Permalink
AVRO-4037: [C++] Add local-timestamp-millis, local-timestamp-micros l…
Browse files Browse the repository at this point in the history
…ogical types (#3053)

* [C++] Add local-timestamp-millis, local-timestamp-micros logical types as defined since specification 1.10.0

* Align exception comment on logical type names

Co-authored-by: Kalle Olavi Niemitalo <[email protected]>

* [C++] Fix local-timestamp-micros exception comment

* [C++] Fix include vector dependency location

---------

Co-authored-by: Kalle Olavi Niemitalo <[email protected]>
  • Loading branch information
glywk and KalleOlaviNiemitalo authored Aug 19, 2024
1 parent fdbf9aa commit 2205c20
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lang/c++/impl/Compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
6 changes: 6 additions & 0 deletions lang/c++/impl/LogicalType.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions lang/c++/impl/Node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,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 "
Expand Down
2 changes: 2 additions & 0 deletions lang/c++/include/avro/LogicalType.hh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public:
TIME_MICROS,
TIMESTAMP_MILLIS,
TIMESTAMP_MICROS,
LOCAL_TIMESTAMP_MILLIS,
LOCAL_TIMESTAMP_MICROS,
DURATION,
UUID
};
Expand Down
1 change: 1 addition & 0 deletions lang/c++/include/avro/Node.hh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <cassert>
#include <memory>
#include <utility>
#include <vector>

#include "CustomAttributes.hh"
#include "Exception.hh"
Expand Down
28 changes: 28 additions & 0 deletions lang/c++/test/SchemaTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"})",

Expand All @@ -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'.
Expand Down Expand Up @@ -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\
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 2205c20

Please sign in to comment.