@@ -66,14 +66,14 @@ cdef class Codec:
66
66
elif type == CODEC_RANGE:
67
67
if format != PG_FORMAT_BINARY:
68
68
raise NotImplementedError (
69
- ' cannot encode type "{}"."{}": text encoding of '
69
+ ' cannot decode type "{}"."{}": text encoding of '
70
70
' range types is not supported' .format(schema, name))
71
71
self .encoder = < codec_encode_func> & self .encode_range
72
72
self .decoder = < codec_decode_func> & self .decode_range
73
73
elif type == CODEC_COMPOSITE:
74
74
if format != PG_FORMAT_BINARY:
75
75
raise NotImplementedError (
76
- ' cannot encode type "{}"."{}": text encoding of '
76
+ ' cannot decode type "{}"."{}": text encoding of '
77
77
' composite types is not supported' .format(schema, name))
78
78
self .encoder = < codec_encode_func> & self .encode_composite
79
79
self .decoder = < codec_decode_func> & self .decode_composite
@@ -243,8 +243,10 @@ cdef class Codec:
243
243
' {!r}, expected {!r}'
244
244
.format(
245
245
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)
248
250
),
249
251
schema = self .schema,
250
252
data_type = self .name,
@@ -567,27 +569,38 @@ cdef class DataCodecConfig:
567
569
encode_func c_encoder = NULL
568
570
decode_func c_decoder = NULL
569
571
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
580
573
581
574
# Clear all previous overrides (this also clears type cache).
582
575
self .remove_python_codec(typeoid, typename, typeschema)
583
576
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))
588
600
589
601
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 )
591
604
self .clear_type_cache()
592
605
593
606
def _set_builtin_type_codec (self , typeoid , typename , typeschema , typekind ,
@@ -596,16 +609,21 @@ cdef class DataCodecConfig:
596
609
Codec codec
597
610
Codec target_codec
598
611
uint32_t oid = pylong_as_oid(typeoid)
599
- uint32_t alias_pid
612
+ uint32_t alias_oid = 0
613
+ bint codec_set = False
600
614
601
615
if format == PG_FORMAT_ANY:
602
616
formats = (PG_FORMAT_BINARY, PG_FORMAT_TEXT)
603
617
else :
604
618
formats = (format,)
605
619
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
+
606
625
for format in formats:
607
- if isinstance (alias_to, int ):
608
- alias_oid = pylong_as_oid(alias_to)
626
+ if alias_oid != 0 :
609
627
target_codec = self .get_codec(alias_oid, format)
610
628
else :
611
629
target_codec = get_extra_codec(alias_to, format)
@@ -619,11 +637,20 @@ cdef class DataCodecConfig:
619
637
codec.schema = typeschema
620
638
codec.kind = typekind
621
639
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
+
625
651
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}' )
627
654
628
655
def set_builtin_type_codec (self , typeoid , typename , typeschema , typekind ,
629
656
alias_to , format = PG_FORMAT_ANY):
@@ -667,7 +694,7 @@ cdef class DataCodecConfig:
667
694
cdef inline Codec get_codec(self , uint32_t oid, ServerDataFormat format):
668
695
cdef Codec codec
669
696
670
- codec = self .get_local_codec (oid)
697
+ codec = self .get_any_local_codec (oid)
671
698
if codec is not None :
672
699
if codec.format != format:
673
700
# The codec for this OID has been overridden by
@@ -686,8 +713,14 @@ cdef class DataCodecConfig:
686
713
except KeyError :
687
714
return None
688
715
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
691
724
692
725
693
726
cdef inline Codec get_core_codec(
@@ -746,7 +779,7 @@ cdef register_core_codec(uint32_t oid,
746
779
str name
747
780
str kind
748
781
749
- name = TYPEMAP [oid]
782
+ name = BUILTIN_TYPE_OID_MAP [oid]
750
783
kind = ' array' if oid in ARRAY_TYPES else ' scalar'
751
784
752
785
codec = Codec(oid)
0 commit comments