@@ -71,6 +71,13 @@ cdef class Codec:
7171 ' range types is not supported' 
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' 
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' 
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' 
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