@@ -66,14 +66,14 @@ cdef class Codec:
6666 elif type == CODEC_RANGE:
6767 if format != PG_FORMAT_BINARY:
6868 raise NotImplementedError (
69- ' cannot encode type "{}"."{}": text encoding of '
69+ ' cannot decode type "{}"."{}": text encoding of '
7070 ' range types is not supported' .format(schema, name))
7171 self .encoder = < codec_encode_func> & self .encode_range
7272 self .decoder = < codec_decode_func> & self .decode_range
7373 elif type == CODEC_COMPOSITE:
7474 if format != PG_FORMAT_BINARY:
7575 raise NotImplementedError (
76- ' cannot encode type "{}"."{}": text encoding of '
76+ ' cannot decode type "{}"."{}": text encoding of '
7777 ' composite types is not supported' .format(schema, name))
7878 self .encoder = < codec_encode_func> & self .encode_composite
7979 self .decoder = < codec_decode_func> & self .decode_composite
@@ -243,8 +243,10 @@ cdef class Codec:
243243 ' {!r}, expected {!r}'
244244 .format(
245245 i,
246- TYPEMAP.get(received_elem_typ, received_elem_typ),
247- TYPEMAP.get(elem_typ, elem_typ)
246+ BUILTIN_TYPE_OID_MAP.get(
247+ received_elem_typ, received_elem_typ),
248+ BUILTIN_TYPE_OID_MAP.get(
249+ elem_typ, elem_typ)
248250 ),
249251 schema = self .schema,
250252 data_type = self .name,
@@ -567,27 +569,38 @@ cdef class DataCodecConfig:
567569 encode_func c_encoder = NULL
568570 decode_func c_decoder = NULL
569571 uint32_t oid = pylong_as_oid(typeoid)
570-
571- if xformat == PG_XFORMAT_TUPLE:
572- core_codec = get_any_core_codec(oid, format, xformat)
573- if core_codec is None :
574- raise exceptions.InterfaceError(
575- " {} type does not support 'tuple' exchange format" .format(
576- typename))
577- c_encoder = core_codec.c_encoder
578- c_decoder = core_codec.c_decoder
579- format = core_codec.format
572+ bint codec_set = False
580573
581574 # Clear all previous overrides (this also clears type cache).
582575 self .remove_python_codec(typeoid, typename, typeschema)
583576
584- self ._custom_type_codecs[typeoid] = \
585- Codec.new_python_codec(oid, typename, typeschema, typekind,
586- encoder, decoder, c_encoder, c_decoder,
587- format, xformat)
577+ if format == PG_FORMAT_ANY:
578+ formats = (PG_FORMAT_TEXT, PG_FORMAT_BINARY)
579+ else :
580+ formats = (format,)
581+
582+ for fmt in formats:
583+ if xformat == PG_XFORMAT_TUPLE:
584+ core_codec = get_core_codec(oid, fmt, xformat)
585+ if core_codec is None :
586+ continue
587+ c_encoder = core_codec.c_encoder
588+ c_decoder = core_codec.c_decoder
589+
590+ self ._custom_type_codecs[typeoid, fmt] = \
591+ Codec.new_python_codec(oid, typename, typeschema, typekind,
592+ encoder, decoder, c_encoder, c_decoder,
593+ fmt, xformat)
594+ codec_set = True
595+
596+ if not codec_set:
597+ raise exceptions.InterfaceError(
598+ " {} type does not support the 'tuple' exchange format" .format(
599+ typename))
588600
589601 def remove_python_codec (self , typeoid , typename , typeschema ):
590- self ._custom_type_codecs.pop(typeoid, None )
602+ for fmt in (PG_FORMAT_BINARY, PG_FORMAT_TEXT):
603+ self ._custom_type_codecs.pop((typeoid, fmt), None )
591604 self .clear_type_cache()
592605
593606 def _set_builtin_type_codec (self , typeoid , typename , typeschema , typekind ,
@@ -596,16 +609,21 @@ cdef class DataCodecConfig:
596609 Codec codec
597610 Codec target_codec
598611 uint32_t oid = pylong_as_oid(typeoid)
599- uint32_t alias_pid
612+ uint32_t alias_oid = 0
613+ bint codec_set = False
600614
601615 if format == PG_FORMAT_ANY:
602616 formats = (PG_FORMAT_BINARY, PG_FORMAT_TEXT)
603617 else :
604618 formats = (format,)
605619
620+ if isinstance (alias_to, int ):
621+ alias_oid = pylong_as_oid(alias_to)
622+ else :
623+ alias_oid = BUILTIN_TYPE_NAME_MAP.get(alias_to, 0 )
624+
606625 for format in formats:
607- if isinstance (alias_to, int ):
608- alias_oid = pylong_as_oid(alias_to)
626+ if alias_oid != 0 :
609627 target_codec = self .get_codec(alias_oid, format)
610628 else :
611629 target_codec = get_extra_codec(alias_to, format)
@@ -619,11 +637,20 @@ cdef class DataCodecConfig:
619637 codec.schema = typeschema
620638 codec.kind = typekind
621639
622- self ._custom_type_codecs[typeoid] = codec
623- break
624- else :
640+ self ._custom_type_codecs[typeoid, format] = codec
641+ codec_set = True
642+
643+ if not codec_set:
644+ if format == PG_FORMAT_BINARY:
645+ codec_str = ' binary'
646+ elif format == PG_FORMAT_TEXT:
647+ codec_str = ' text'
648+ else :
649+ codec_str = ' text or binary'
650+
625651 raise exceptions.InterfaceError(
626- ' invalid builtin codec reference: {}' .format(alias_to))
652+ f' cannot alias {typename} to {alias_to}: '
653+ f' there is no {codec_str} codec for {alias_to}' )
627654
628655 def set_builtin_type_codec (self , typeoid , typename , typeschema , typekind ,
629656 alias_to , format = PG_FORMAT_ANY):
@@ -667,7 +694,7 @@ cdef class DataCodecConfig:
667694 cdef inline Codec get_codec(self , uint32_t oid, ServerDataFormat format):
668695 cdef Codec codec
669696
670- codec = self .get_local_codec (oid)
697+ codec = self .get_any_local_codec (oid)
671698 if codec is not None :
672699 if codec.format != format:
673700 # The codec for this OID has been overridden by
@@ -686,8 +713,14 @@ cdef class DataCodecConfig:
686713 except KeyError :
687714 return None
688715
689- cdef inline Codec get_local_codec(self , uint32_t oid):
690- return self ._custom_type_codecs.get(oid)
716+ cdef inline Codec get_any_local_codec(self , uint32_t oid):
717+ cdef Codec codec
718+
719+ codec = self ._custom_type_codecs.get((oid, PG_FORMAT_BINARY))
720+ if codec is None :
721+ return self ._custom_type_codecs.get((oid, PG_FORMAT_TEXT))
722+ else :
723+ return codec
691724
692725
693726cdef inline Codec get_core_codec(
@@ -746,7 +779,7 @@ cdef register_core_codec(uint32_t oid,
746779 str name
747780 str kind
748781
749- name = TYPEMAP [oid]
782+ name = BUILTIN_TYPE_OID_MAP [oid]
750783 kind = ' array' if oid in ARRAY_TYPES else ' scalar'
751784
752785 codec = Codec(oid)
0 commit comments