@@ -71,6 +71,13 @@ cdef class Codec:
7171 ' range types is not supported' .format(schema, name))
7272 self .encoder = < codec_encode_func> & self .encode_range
7373 self .decoder = < codec_decode_func> & self .decode_range
74+ elif type == CODEC_MULTIRANGE:
75+ if format != PG_FORMAT_BINARY:
76+ raise exceptions.UnsupportedClientFeatureError(
77+ ' cannot decode type "{}"."{}": text encoding of '
78+ ' range types is not supported' .format(schema, name))
79+ self .encoder = < codec_encode_func> & self .encode_multirange
80+ self .decoder = < codec_decode_func> & self .decode_multirange
7481 elif type == CODEC_COMPOSITE:
7582 if format != PG_FORMAT_BINARY:
7683 raise exceptions.UnsupportedClientFeatureError(
@@ -122,6 +129,12 @@ cdef class Codec:
122129 codec_encode_func_ex,
123130 < void * > (< cpython.PyObject> self .element_codec))
124131
132+ cdef encode_multirange(self , ConnectionSettings settings, WriteBuffer buf,
133+ object obj):
134+ multirange_encode(settings, buf, obj, self .element_codec.oid,
135+ codec_encode_func_ex,
136+ < void * > (< cpython.PyObject> self .element_codec))
137+
125138 cdef encode_composite(self , ConnectionSettings settings, WriteBuffer buf,
126139 object obj):
127140 cdef:
@@ -209,6 +222,10 @@ cdef class Codec:
209222 return range_decode(settings, buf, codec_decode_func_ex,
210223 < void * > (< cpython.PyObject> self .element_codec))
211224
225+ cdef decode_multirange(self , ConnectionSettings settings, FRBuffer * buf):
226+ return multirange_decode(settings, buf, codec_decode_func_ex,
227+ < void * > (< cpython.PyObject> self .element_codec))
228+
212229 cdef decode_composite(self , ConnectionSettings settings,
213230 FRBuffer * buf):
214231 cdef:
@@ -294,7 +311,11 @@ cdef class Codec:
294311 if self .c_encoder is not NULL or self .py_encoder is not None :
295312 return True
296313
297- elif self .type == CODEC_ARRAY or self .type == CODEC_RANGE:
314+ elif (
315+ self .type == CODEC_ARRAY
316+ or self .type == CODEC_RANGE
317+ or self .type == CODEC_MULTIRANGE
318+ ):
298319 return self .element_codec.has_encoder()
299320
300321 elif self .type == CODEC_COMPOSITE:
@@ -312,7 +333,11 @@ cdef class Codec:
312333 if self .c_decoder is not NULL or self .py_decoder is not None :
313334 return True
314335
315- elif self .type == CODEC_ARRAY or self .type == CODEC_RANGE:
336+ elif (
337+ self .type == CODEC_ARRAY
338+ or self .type == CODEC_RANGE
339+ or self .type == CODEC_MULTIRANGE
340+ ):
316341 return self .element_codec.has_decoder()
317342
318343 elif self .type == CODEC_COMPOSITE:
@@ -358,6 +383,18 @@ cdef class Codec:
358383 None , None , None , 0 )
359384 return codec
360385
386+ @staticmethod
387+ cdef Codec new_multirange_codec(uint32_t oid,
388+ str name,
389+ str schema,
390+ Codec element_codec):
391+ cdef Codec codec
392+ codec = Codec(oid)
393+ codec.init(name, schema, ' multirange' , CODEC_MULTIRANGE,
394+ element_codec.format, PG_XFORMAT_OBJECT, NULL , NULL ,
395+ None , None , element_codec, None , None , None , 0 )
396+ return codec
397+
361398 @staticmethod
362399 cdef Codec new_composite_codec(uint32_t oid,
363400 str name,
@@ -536,6 +573,21 @@ cdef class DataCodecConfig:
536573 self ._derived_type_codecs[oid, elem_codec.format] = \
537574 Codec.new_range_codec(oid, name, schema, elem_codec)
538575
576+ elif ti[' kind' ] == b' m' :
577+ # Multirange type
578+
579+ if not range_subtype_oid:
580+ raise exceptions.InternalClientError(
581+ f' type record missing base type for multirange {oid}' )
582+
583+ elem_codec = self .get_codec(range_subtype_oid, PG_FORMAT_ANY)
584+ if elem_codec is None :
585+ elem_codec = self .declare_fallback_codec(
586+ range_subtype_oid, ti[' range_subtype_name' ], schema)
587+
588+ self ._derived_type_codecs[oid, elem_codec.format] = \
589+ Codec.new_multirange_codec(oid, name, schema, elem_codec)
590+
539591 elif ti[' kind' ] == b' e' :
540592 # Enum types are essentially text
541593 self ._set_builtin_type_codec(oid, name, schema, ' scalar' ,
0 commit comments