@@ -389,6 +389,12 @@ nlohmann::json ToJson(const Type& type) {
389389 return " uuid" ;
390390 case TypeId::kUnknown :
391391 return " unknown" ;
392+ case TypeId::kVariant :
393+ return " variant" ;
394+ case TypeId::kGeometry :
395+ return type.ToString ();
396+ case TypeId::kGeography :
397+ return type.ToString ();
392398 }
393399 std::unreachable ();
394400}
@@ -459,9 +465,10 @@ Result<std::unique_ptr<Type>> ListTypeFromJson(const nlohmann::json& json) {
459465 ICEBERG_ASSIGN_OR_RAISE (auto element_required,
460466 GetJsonValue<bool >(json, kElementRequired ));
461467
462- return std::make_unique<ListType>(
463- SchemaField (element_id, std::string (ListType::kElementName ),
464- std::move (element_type), !element_required));
468+ ICEBERG_ASSIGN_OR_RAISE (auto type, ListType::Make (SchemaField (
469+ element_id, std::string (ListType::kElementName ),
470+ std::move (element_type), !element_required)));
471+ return std::unique_ptr<Type>(std::move (type));
465472}
466473
467474Result<std::unique_ptr<Type>> MapTypeFromJson (const nlohmann::json& json) {
@@ -478,79 +485,126 @@ Result<std::unique_ptr<Type>> MapTypeFromJson(const nlohmann::json& json) {
478485 /* optional=*/ false );
479486 SchemaField value_field (value_id, std::string (MapType::kValueName ),
480487 std::move (value_type), !value_required);
481- return std::make_unique<MapType>(std::move (key_field), std::move (value_field));
488+ ICEBERG_ASSIGN_OR_RAISE (auto type,
489+ MapType::Make (std::move (key_field), std::move (value_field)));
490+ return std::unique_ptr<Type>(std::move (type));
482491}
483492
484493} // namespace
485494
486495Result<std::unique_ptr<Type>> TypeFromJson (const nlohmann::json& json) {
487496 if (json.is_string ()) {
488- std::string type_str = json.get <std::string>();
489- if (type_str == " boolean" ) {
497+ const auto type_name = json.get <std::string>();
498+ const auto normalized_type_name = StringUtils::ToLower (type_name);
499+ if (normalized_type_name == " boolean" ) {
490500 return std::make_unique<BooleanType>();
491- } else if (type_str == " int" ) {
501+ } else if (normalized_type_name == " int" ) {
492502 return std::make_unique<IntType>();
493- } else if (type_str == " long" ) {
503+ } else if (normalized_type_name == " long" ) {
494504 return std::make_unique<LongType>();
495- } else if (type_str == " float" ) {
505+ } else if (normalized_type_name == " float" ) {
496506 return std::make_unique<FloatType>();
497- } else if (type_str == " double" ) {
507+ } else if (normalized_type_name == " double" ) {
498508 return std::make_unique<DoubleType>();
499- } else if (type_str == " date" ) {
509+ } else if (normalized_type_name == " date" ) {
500510 return std::make_unique<DateType>();
501- } else if (type_str == " time" ) {
511+ } else if (normalized_type_name == " time" ) {
502512 return std::make_unique<TimeType>();
503- } else if (type_str == " timestamp" ) {
513+ } else if (normalized_type_name == " timestamp" ) {
504514 return std::make_unique<TimestampType>();
505- } else if (type_str == " timestamptz" ) {
515+ } else if (normalized_type_name == " timestamptz" ) {
506516 return std::make_unique<TimestampTzType>();
507- } else if (type_str == " timestamp_ns" ) {
517+ } else if (normalized_type_name == " timestamp_ns" ) {
508518 return std::make_unique<TimestampNsType>();
509- } else if (type_str == " timestamptz_ns" ) {
519+ } else if (normalized_type_name == " timestamptz_ns" ) {
510520 return std::make_unique<TimestampTzNsType>();
511- } else if (type_str == " string" ) {
521+ } else if (normalized_type_name == " string" ) {
512522 return std::make_unique<StringType>();
513- } else if (type_str == " binary" ) {
523+ } else if (normalized_type_name == " binary" ) {
514524 return std::make_unique<BinaryType>();
515- } else if (type_str == " uuid" ) {
525+ } else if (normalized_type_name == " uuid" ) {
516526 return std::make_unique<UuidType>();
517- } else if (type_str == " unknown" ) {
527+ } else if (normalized_type_name == " unknown" ) {
518528 return std::make_unique<UnknownType>();
519- } else if (type_str.starts_with (" fixed" )) {
520- std::regex fixed_regex (R"( fixed\[\s*(\d+)\s*\])" );
529+ } else if (normalized_type_name == " variant" ) {
530+ return std::make_unique<VariantType>();
531+ } else if (normalized_type_name.starts_with (" fixed" )) {
532+ static const std::regex kFixedRegex (R"( fixed\[\s*(\d+)\s*\])" );
521533 std::smatch match;
522- if (std::regex_match (type_str , match, fixed_regex )) {
534+ if (std::regex_match (normalized_type_name , match, kFixedRegex )) {
523535 ICEBERG_ASSIGN_OR_RAISE (auto length,
524536 StringUtils::ParseNumber<int32_t >(match[1 ].str ()));
525537 return std::make_unique<FixedType>(length);
526538 }
527- return JsonParseError (" Invalid fixed type: {}" , type_str );
528- } else if (type_str .starts_with (" decimal" )) {
529- std::regex decimal_regex (R"( decimal\(\s*(\d+)\s*,\s*(\d+)\s*\))" );
539+ return JsonParseError (" Invalid fixed type: {}" , type_name );
540+ } else if (normalized_type_name .starts_with (" decimal" )) {
541+ static const std::regex kDecimalRegex (R"( decimal\(\s*(\d+)\s*,\s*(\d+)\s*\))" );
530542 std::smatch match;
531- if (std::regex_match (type_str , match, decimal_regex )) {
543+ if (std::regex_match (normalized_type_name , match, kDecimalRegex )) {
532544 ICEBERG_ASSIGN_OR_RAISE (auto precision,
533545 StringUtils::ParseNumber<int32_t >(match[1 ].str ()));
534546 ICEBERG_ASSIGN_OR_RAISE (auto scale,
535547 StringUtils::ParseNumber<int32_t >(match[2 ].str ()));
536548 return std::make_unique<DecimalType>(precision, scale);
537549 }
538- return JsonParseError (" Invalid decimal type: {}" , type_str);
550+ return JsonParseError (" Invalid decimal type: {}" , type_name);
551+ } else if (normalized_type_name.starts_with (" geometry" )) {
552+ static const std::regex kGeometryRegex (R"( geometry\s*(?:\(\s*([^)]*?)\s*\))?)" ,
553+ std::regex_constants::icase);
554+ std::smatch match;
555+ if (std::regex_match (type_name, match, kGeometryRegex )) {
556+ if (match[1 ].matched ) {
557+ auto crs = match[1 ].str ();
558+ if (crs.empty ()) {
559+ return JsonParseError (" Invalid geometry type: {}" , type_name);
560+ }
561+ ICEBERG_ASSIGN_OR_RAISE (auto type, GeometryType::Make (std::move (crs)));
562+ return std::unique_ptr<Type>(std::move (type));
563+ }
564+ ICEBERG_ASSIGN_OR_RAISE (auto type, GeometryType::Make ());
565+ return std::unique_ptr<Type>(std::move (type));
566+ }
567+ return JsonParseError (" Invalid geometry type: {}" , type_name);
568+ } else if (normalized_type_name.starts_with (" geography" )) {
569+ static const std::regex kGeographyRegex (
570+ R"( geography\s*(?:\(\s*([^,]*?)\s*(?:,\s*(\w*)\s*)?\))?)" ,
571+ std::regex_constants::icase);
572+ std::smatch match;
573+ if (std::regex_match (type_name, match, kGeographyRegex )) {
574+ auto crs = match[1 ].str ();
575+ if (match[1 ].matched && crs.empty ()) {
576+ return JsonParseError (" Invalid geography type: {}" , type_name);
577+ }
578+ if (match[2 ].matched ) {
579+ ICEBERG_ASSIGN_OR_RAISE (auto algorithm,
580+ EdgeAlgorithmFromString (match[2 ].str ()));
581+ ICEBERG_ASSIGN_OR_RAISE (auto type,
582+ GeographyType::Make (std::move (crs), algorithm));
583+ return std::unique_ptr<Type>(std::move (type));
584+ }
585+ if (match[1 ].matched ) {
586+ ICEBERG_ASSIGN_OR_RAISE (auto type, GeographyType::Make (std::move (crs)));
587+ return std::unique_ptr<Type>(std::move (type));
588+ }
589+ ICEBERG_ASSIGN_OR_RAISE (auto type, GeographyType::Make ());
590+ return std::unique_ptr<Type>(std::move (type));
591+ }
592+ return JsonParseError (" Invalid geography type: {}" , type_name);
539593 } else {
540- return JsonParseError (" Unknown primitive type: {}" , type_str );
594+ return JsonParseError (" Cannot parse type string : {}" , type_name );
541595 }
542596 }
543597
544598 // For complex types like struct, list, and map
545- ICEBERG_ASSIGN_OR_RAISE (auto type_str , GetJsonValue<std::string>(json, kType ));
546- if (type_str == kStruct ) {
599+ ICEBERG_ASSIGN_OR_RAISE (auto complex_type_name , GetJsonValue<std::string>(json, kType ));
600+ if (complex_type_name == kStruct ) {
547601 return StructTypeFromJson (json);
548- } else if (type_str == kList ) {
602+ } else if (complex_type_name == kList ) {
549603 return ListTypeFromJson (json);
550- } else if (type_str == kMap ) {
604+ } else if (complex_type_name == kMap ) {
551605 return MapTypeFromJson (json);
552606 } else {
553- return JsonParseError (" Unknown complex type: {}" , type_str );
607+ return JsonParseError (" Unknown complex type: {}" , complex_type_name );
554608 }
555609}
556610
0 commit comments