@@ -238,6 +238,9 @@ struct ParquetWriteBindData : public TableFunctionData {
238238
239239 // ! Which encodings to include when writing
240240 ParquetVersion parquet_version = ParquetVersion::V1;
241+
242+ // ! Which geo-parquet version to use when writing
243+ GeoParquetVersion geoparquet_version = GeoParquetVersion::V1;
241244};
242245
243246struct ParquetWriteGlobalState : public GlobalFunctionData {
@@ -291,6 +294,7 @@ static void ParquetListCopyOptions(ClientContext &context, CopyOptionsInput &inp
291294 copy_options[" binary_as_string" ] = CopyOption (LogicalType::BOOLEAN, CopyOptionMode::READ_ONLY);
292295 copy_options[" file_row_number" ] = CopyOption (LogicalType::BOOLEAN, CopyOptionMode::READ_ONLY);
293296 copy_options[" can_have_nan" ] = CopyOption (LogicalType::BOOLEAN, CopyOptionMode::READ_ONLY);
297+ copy_options[" geoparquet_version" ] = CopyOption (LogicalType::VARCHAR, CopyOptionMode::WRITE_ONLY);
294298}
295299
296300static unique_ptr<FunctionData> ParquetWriteBind (ClientContext &context, CopyFunctionBindInput &input,
@@ -426,6 +430,19 @@ static unique_ptr<FunctionData> ParquetWriteBind(ClientContext &context, CopyFun
426430 } else {
427431 throw BinderException (" Expected parquet_version 'V1' or 'V2'" );
428432 }
433+ } else if (loption == " geoparquet_version" ) {
434+ const auto roption = StringUtil::Upper (option.second [0 ].ToString ());
435+ if (roption == " NONE" ) {
436+ bind_data->geoparquet_version = GeoParquetVersion::NONE;
437+ } else if (roption == " V1" ) {
438+ bind_data->geoparquet_version = GeoParquetVersion::V1;
439+ } else if (roption == " V2" ) {
440+ bind_data->geoparquet_version = GeoParquetVersion::V2;
441+ } else if (roption == " BOTH" ) {
442+ bind_data->geoparquet_version = GeoParquetVersion::BOTH;
443+ } else {
444+ throw BinderException (" Expected geoparquet_version 'NONE', 'V1' or 'BOTH'" );
445+ }
429446 } else {
430447 throw InternalException (" Unrecognized option for PARQUET: %s" , option.first .c_str ());
431448 }
@@ -457,7 +474,8 @@ static unique_ptr<GlobalFunctionData> ParquetWriteInitializeGlobal(ClientContext
457474 parquet_bind.field_ids .Copy (), parquet_bind.kv_metadata , parquet_bind.encryption_config ,
458475 parquet_bind.dictionary_size_limit , parquet_bind.string_dictionary_page_size_limit ,
459476 parquet_bind.enable_bloom_filters , parquet_bind.bloom_filter_false_positive_ratio ,
460- parquet_bind.compression_level , parquet_bind.debug_use_openssl , parquet_bind.parquet_version );
477+ parquet_bind.compression_level , parquet_bind.debug_use_openssl , parquet_bind.parquet_version ,
478+ parquet_bind.geoparquet_version );
461479 return std::move (global_state);
462480}
463481
@@ -626,6 +644,39 @@ ParquetVersion EnumUtil::FromString<ParquetVersion>(const char *value) {
626644 throw NotImplementedException (StringUtil::Format (" Enum value: '%s' not implemented" , value));
627645}
628646
647+ template <>
648+ const char *EnumUtil::ToChars<GeoParquetVersion>(GeoParquetVersion value) {
649+ switch (value) {
650+ case GeoParquetVersion::NONE:
651+ return " NONE" ;
652+ case GeoParquetVersion::V1:
653+ return " V1" ;
654+ case GeoParquetVersion::V2:
655+ return " V2" ;
656+ case GeoParquetVersion::BOTH:
657+ return " BOTH" ;
658+ default :
659+ throw NotImplementedException (StringUtil::Format (" Enum value: '%s' not implemented" , value));
660+ }
661+ }
662+
663+ template <>
664+ GeoParquetVersion EnumUtil::FromString<GeoParquetVersion>(const char *value) {
665+ if (StringUtil::Equals (value, " NONE" )) {
666+ return GeoParquetVersion::NONE;
667+ }
668+ if (StringUtil::Equals (value, " V1" )) {
669+ return GeoParquetVersion::V1;
670+ }
671+ if (StringUtil::Equals (value, " V2" )) {
672+ return GeoParquetVersion::V2;
673+ }
674+ if (StringUtil::Equals (value, " BOTH" )) {
675+ return GeoParquetVersion::BOTH;
676+ }
677+ throw NotImplementedException (StringUtil::Format (" Enum value: '%s' not implemented" , value));
678+ }
679+
629680static optional_idx SerializeCompressionLevel (const int64_t compression_level) {
630681 return compression_level < 0 ? NumericLimits<idx_t >::Maximum () - NumericCast<idx_t >(AbsValue (compression_level))
631682 : NumericCast<idx_t >(compression_level);
@@ -679,6 +730,8 @@ static void ParquetCopySerialize(Serializer &serializer, const FunctionData &bin
679730 serializer.WritePropertyWithDefault (115 , " string_dictionary_page_size_limit" ,
680731 bind_data.string_dictionary_page_size_limit ,
681732 default_value.string_dictionary_page_size_limit );
733+ serializer.WritePropertyWithDefault (116 , " geoparquet_version" , bind_data.geoparquet_version ,
734+ default_value.geoparquet_version );
682735}
683736
684737static unique_ptr<FunctionData> ParquetCopyDeserialize (Deserializer &deserializer, CopyFunction &function) {
@@ -711,6 +764,8 @@ static unique_ptr<FunctionData> ParquetCopyDeserialize(Deserializer &deserialize
711764 deserializer.ReadPropertyWithExplicitDefault (114 , " parquet_version" , default_value.parquet_version );
712765 data->string_dictionary_page_size_limit = deserializer.ReadPropertyWithExplicitDefault (
713766 115 , " string_dictionary_page_size_limit" , default_value.string_dictionary_page_size_limit );
767+ data->geoparquet_version =
768+ deserializer.ReadPropertyWithExplicitDefault (116 , " geoparquet_version" , default_value.geoparquet_version );
714769
715770 return std::move (data);
716771}
0 commit comments