Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
33 changes: 33 additions & 0 deletions src/iceberg/type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <format>
#include <iterator>
#include <memory>

#include "iceberg/exception.h"
#include "iceberg/util/formatter.h" // IWYU pragma: keep
Expand Down Expand Up @@ -286,4 +287,36 @@ TypeId BinaryType::type_id() const { return kTypeId; }
std::string BinaryType::ToString() const { return "binary"; }
bool BinaryType::Equals(const Type& other) const { return other.type_id() == kTypeId; }

// ----------------------------------------------------------------------
// Factory functions for creating primitive data types

#define TYPE_FACTORY(NAME, KLASS) \
const std::shared_ptr<KLASS>& NAME() { \
static std::shared_ptr<KLASS> result = std::make_shared<KLASS>(); \
return result; \
}

TYPE_FACTORY(boolean, BooleanType)
TYPE_FACTORY(int32, IntType)
TYPE_FACTORY(int64, LongType)
TYPE_FACTORY(float32, FloatType)
TYPE_FACTORY(float64, DoubleType)
TYPE_FACTORY(date, DateType)
TYPE_FACTORY(time, TimeType)
TYPE_FACTORY(timestamp, TimestampType)
TYPE_FACTORY(timestamp_tz, TimestampTzType)
TYPE_FACTORY(binary, BinaryType)
TYPE_FACTORY(string, StringType)
TYPE_FACTORY(uuid, UuidType)

#undef TYPE_FACTORY

std::shared_ptr<DecimalType> decimal(int32_t precision, int32_t scale) {
return std::make_shared<DecimalType>(precision, scale);
}

std::shared_ptr<FixedType> fixed(int32_t length) {
return std::make_shared<FixedType>(length);
}

} // namespace iceberg
44 changes: 44 additions & 0 deletions src/iceberg/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,4 +446,48 @@ class ICEBERG_EXPORT UuidType : public PrimitiveType {

/// @}

/// \defgroup type-factories Factory functions for creating primitive data types
///
/// Factory functions for creating primitive data types
/// @{

/// \brief Return a BooleanType instance.
ICEBERG_EXPORT const std::shared_ptr<BooleanType>& boolean();
/// \brief Return an IntType instance.
ICEBERG_EXPORT const std::shared_ptr<IntType>& int32();
/// \brief Return a LongType instance.
ICEBERG_EXPORT const std::shared_ptr<LongType>& int64();
/// \brief Return a FloatType instance.
ICEBERG_EXPORT const std::shared_ptr<FloatType>& float32();
/// \brief Return a DoubleType instance.
ICEBERG_EXPORT const std::shared_ptr<DoubleType>& float64();
/// \brief Return a DateType instance.
ICEBERG_EXPORT const std::shared_ptr<DateType>& date();
/// \brief Return a TimeType instance.
ICEBERG_EXPORT const std::shared_ptr<TimeType>& time();
/// \brief Return a TimestampType instance.
ICEBERG_EXPORT const std::shared_ptr<TimestampType>& timestamp();
/// \brief Return a TimestampTzType instance.
ICEBERG_EXPORT const std::shared_ptr<TimestampTzType>& timestamp_tz();
/// \brief Return a BinaryType instance.
ICEBERG_EXPORT const std::shared_ptr<BinaryType>& binary();
/// \brief Return a StringType instance.
ICEBERG_EXPORT const std::shared_ptr<StringType>& string();
/// \brief Return a UuidType instance.
ICEBERG_EXPORT const std::shared_ptr<UuidType>& uuid();

/// \brief Create a DecimalType with the given precision and scale.
/// \param precision The number of decimal digits (max 38).
/// \param scale The number of decimal digits after the decimal point (0 to
/// precision).
/// \return A shared pointer to the DecimalType instance.
ICEBERG_EXPORT std::shared_ptr<DecimalType> decimal(int32_t precision, int32_t scale);

/// \brief Create a FixedType with the given length.
/// \param length The number of bytes to store (must be >= 0).
/// \return A shared pointer to the FixedType instance.
ICEBERG_EXPORT std::shared_ptr<FixedType> fixed(int32_t length);

/// @}

} // namespace iceberg
76 changes: 32 additions & 44 deletions test/type_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

#include <format>
#include <memory>
#include <stdexcept>
#include <string>

#include <gmock/gmock.h>
Expand Down Expand Up @@ -91,112 +90,112 @@ TEST_P(TypeTest, StdFormat) {
const static std::array<TypeTestCase, 16> kPrimitiveTypes = {{
{
.name = "boolean",
.type = std::make_shared<iceberg::BooleanType>(),
.type = iceberg::boolean(),
.type_id = iceberg::TypeId::kBoolean,
.primitive = true,
.repr = "boolean",
},
{
.name = "int",
.type = std::make_shared<iceberg::IntType>(),
.type = iceberg::int32(),
.type_id = iceberg::TypeId::kInt,
.primitive = true,
.repr = "int",
},
{
.name = "long",
.type = std::make_shared<iceberg::LongType>(),
.type = iceberg::int64(),
.type_id = iceberg::TypeId::kLong,
.primitive = true,
.repr = "long",
},
{
.name = "float",
.type = std::make_shared<iceberg::FloatType>(),
.type = iceberg::float32(),
.type_id = iceberg::TypeId::kFloat,
.primitive = true,
.repr = "float",
},
{
.name = "double",
.type = std::make_shared<iceberg::DoubleType>(),
.type = iceberg::float64(),
.type_id = iceberg::TypeId::kDouble,
.primitive = true,
.repr = "double",
},
{
.name = "decimal9_2",
.type = std::make_shared<iceberg::DecimalType>(9, 2),
.type = iceberg::decimal(9, 2),
.type_id = iceberg::TypeId::kDecimal,
.primitive = true,
.repr = "decimal(9, 2)",
},
{
.name = "decimal38_10",
.type = std::make_shared<iceberg::DecimalType>(38, 10),
.type = iceberg::decimal(38, 10),
.type_id = iceberg::TypeId::kDecimal,
.primitive = true,
.repr = "decimal(38, 10)",
},
{
.name = "date",
.type = std::make_shared<iceberg::DateType>(),
.type = iceberg::date(),
.type_id = iceberg::TypeId::kDate,
.primitive = true,
.repr = "date",
},
{
.name = "time",
.type = std::make_shared<iceberg::TimeType>(),
.type = iceberg::time(),
.type_id = iceberg::TypeId::kTime,
.primitive = true,
.repr = "time",
},
{
.name = "timestamp",
.type = std::make_shared<iceberg::TimestampType>(),
.type = iceberg::timestamp(),
.type_id = iceberg::TypeId::kTimestamp,
.primitive = true,
.repr = "timestamp",
},
{
.name = "timestamptz",
.type = std::make_shared<iceberg::TimestampTzType>(),
.type = iceberg::timestamp_tz(),
.type_id = iceberg::TypeId::kTimestampTz,
.primitive = true,
.repr = "timestamptz",
},
{
.name = "binary",
.type = std::make_shared<iceberg::BinaryType>(),
.type = iceberg::binary(),
.type_id = iceberg::TypeId::kBinary,
.primitive = true,
.repr = "binary",
},
{
.name = "string",
.type = std::make_shared<iceberg::StringType>(),
.type = iceberg::string(),
.type_id = iceberg::TypeId::kString,
.primitive = true,
.repr = "string",
},
{
.name = "fixed10",
.type = std::make_shared<iceberg::FixedType>(10),
.type = iceberg::fixed(10),
.type_id = iceberg::TypeId::kFixed,
.primitive = true,
.repr = "fixed(10)",
},
{
.name = "fixed255",
.type = std::make_shared<iceberg::FixedType>(255),
.type = iceberg::fixed(255),
.type_id = iceberg::TypeId::kFixed,
.primitive = true,
.repr = "fixed(255)",
},
{
.name = "uuid",
.type = std::make_shared<iceberg::UuidType>(),
.type = iceberg::uuid(),
.type_id = iceberg::TypeId::kUuid,
.primitive = true,
.repr = "uuid",
Expand All @@ -206,41 +205,33 @@ const static std::array<TypeTestCase, 16> kPrimitiveTypes = {{
const static std::array<TypeTestCase, 4> kNestedTypes = {{
{
.name = "list_int",
.type = std::make_shared<iceberg::ListType>(
1, std::make_shared<iceberg::IntType>(), true),
.type = std::make_shared<iceberg::ListType>(1, iceberg::int32(), true),
.type_id = iceberg::TypeId::kList,
.primitive = false,
.repr = "list<element (1): int (optional)>",
},
{
.name = "list_list_int",
.type = std::make_shared<iceberg::ListType>(
1,
std::make_shared<iceberg::ListType>(2, std::make_shared<iceberg::IntType>(),
true),
false),
1, std::make_shared<iceberg::ListType>(2, iceberg::int32(), true), false),
.type_id = iceberg::TypeId::kList,
.primitive = false,
.repr = "list<element (1): list<element (2): int (optional)> (required)>",
},
{
.name = "map_int_string",
.type = std::make_shared<iceberg::MapType>(
iceberg::SchemaField::MakeRequired(1, "key",
std::make_shared<iceberg::LongType>()),
iceberg::SchemaField::MakeRequired(2, "value",
std::make_shared<iceberg::StringType>())),
iceberg::SchemaField::MakeRequired(1, "key", iceberg::int64()),
iceberg::SchemaField::MakeRequired(2, "value", iceberg::string())),
.type_id = iceberg::TypeId::kMap,
.primitive = false,
.repr = "map<key (1): long (required): value (2): string (required)>",
},
{
.name = "struct",
.type = std::make_shared<iceberg::StructType>(std::vector<iceberg::SchemaField>{
iceberg::SchemaField::MakeRequired(1, "foo",
std::make_shared<iceberg::LongType>()),
iceberg::SchemaField::MakeOptional(2, "bar",
std::make_shared<iceberg::StringType>()),
iceberg::SchemaField::MakeRequired(1, "foo", iceberg::int64()),
iceberg::SchemaField::MakeOptional(2, "bar", iceberg::string()),
}),
.type_id = iceberg::TypeId::kStruct,
.primitive = false,
Expand Down Expand Up @@ -344,8 +335,8 @@ TEST(TypeTest, List) {

TEST(TypeTest, Map) {
{
iceberg::SchemaField key(5, "key", std::make_shared<iceberg::IntType>(), true);
iceberg::SchemaField value(7, "value", std::make_shared<iceberg::StringType>(), true);
iceberg::SchemaField key(5, "key", iceberg::int32(), true);
iceberg::SchemaField value(7, "value", iceberg::string(), true);
iceberg::MapType map(key, value);
std::span<const iceberg::SchemaField> fields = map.fields();
ASSERT_EQ(2, fields.size());
Expand All @@ -365,18 +356,16 @@ TEST(TypeTest, Map) {
}
ASSERT_THAT(
[]() {
iceberg::SchemaField key(5, "notkey", std::make_shared<iceberg::IntType>(), true);
iceberg::SchemaField value(7, "value", std::make_shared<iceberg::StringType>(),
true);
iceberg::SchemaField key(5, "notkey", iceberg::int32(), true);
iceberg::SchemaField value(7, "value", iceberg::string(), true);
iceberg::MapType map(key, value);
},
::testing::ThrowsMessage<iceberg::IcebergError>(
::testing::HasSubstr("key field name should be 'key', was 'notkey'")));
ASSERT_THAT(
[]() {
iceberg::SchemaField key(5, "key", std::make_shared<iceberg::IntType>(), true);
iceberg::SchemaField value(7, "notvalue", std::make_shared<iceberg::StringType>(),
true);
iceberg::SchemaField key(5, "key", iceberg::int32(), true);
iceberg::SchemaField value(7, "notvalue", iceberg::string(), true);
iceberg::MapType map(key, value);
},
::testing::ThrowsMessage<iceberg::IcebergError>(
Expand All @@ -385,8 +374,8 @@ TEST(TypeTest, Map) {

TEST(TypeTest, Struct) {
{
iceberg::SchemaField field1(5, "foo", std::make_shared<iceberg::IntType>(), true);
iceberg::SchemaField field2(7, "bar", std::make_shared<iceberg::StringType>(), true);
iceberg::SchemaField field1(5, "foo", iceberg::int32(), true);
iceberg::SchemaField field2(7, "bar", iceberg::string(), true);
iceberg::StructType struct_({field1, field2});
std::span<const iceberg::SchemaField> fields = struct_.fields();
ASSERT_EQ(2, fields.size());
Expand All @@ -406,9 +395,8 @@ TEST(TypeTest, Struct) {
}
ASSERT_THAT(
[]() {
iceberg::SchemaField field1(5, "foo", std::make_shared<iceberg::IntType>(), true);
iceberg::SchemaField field2(5, "bar", std::make_shared<iceberg::StringType>(),
true);
iceberg::SchemaField field1(5, "foo", iceberg::int32(), true);
iceberg::SchemaField field2(5, "bar", iceberg::string(), true);
iceberg::StructType struct_({field1, field2});
},
::testing::ThrowsMessage<iceberg::IcebergError>(
Expand Down
Loading