@@ -440,14 +440,7 @@ cdef class DataCodecConfig:
440440 for ti in types:
441441 oid = ti[' oid' ]
442442
443- if not ti[' has_bin_io' ]:
444- format = PG_FORMAT_TEXT
445- else :
446- format = PG_FORMAT_BINARY
447-
448- has_text_elements = False
449-
450- if self .get_codec(oid, format) is not None :
443+ if self .get_codec(oid, PG_FORMAT_ANY) is not None :
451444 continue
452445
453446 name = ti[' name' ]
@@ -468,92 +461,79 @@ cdef class DataCodecConfig:
468461 name = name[1 :]
469462 name = ' {}[]' .format(name)
470463
471- if ti[' elem_has_bin_io' ]:
472- elem_format = PG_FORMAT_BINARY
473- else :
474- elem_format = PG_FORMAT_TEXT
475-
476- elem_codec = self .get_codec(array_element_oid, elem_format)
464+ elem_codec = self .get_codec(array_element_oid, PG_FORMAT_ANY)
477465 if elem_codec is None :
478- elem_format = PG_FORMAT_TEXT
479466 elem_codec = self .declare_fallback_codec(
480- array_element_oid, name , schema)
467+ array_element_oid, ti[ ' elemtype_name ' ] , schema)
481468
482469 elem_delim = < Py_UCS4> ti[' elemdelim' ][0 ]
483470
484- self ._derived_type_codecs[oid, elem_format ] = \
471+ self ._derived_type_codecs[oid, elem_codec.format ] = \
485472 Codec.new_array_codec(
486473 oid, name, schema, elem_codec, elem_delim)
487474
488475 elif ti[' kind' ] == b' c' :
476+ # Composite type
477+
489478 if not comp_type_attrs:
490479 raise exceptions.InternalClientError(
491- ' type record missing field types for '
492- ' composite {}' .format(oid))
493-
494- # Composite type
480+ f' type record missing field types for composite {oid}' )
495481
496482 comp_elem_codecs = []
483+ has_text_elements = False
497484
498485 for typoid in comp_type_attrs:
499- elem_codec = self .get_codec(typoid, PG_FORMAT_BINARY)
500- if elem_codec is None :
501- elem_codec = self .get_codec(typoid, PG_FORMAT_TEXT)
502- has_text_elements = True
486+ elem_codec = self .get_codec(typoid, PG_FORMAT_ANY)
503487 if elem_codec is None :
504488 raise exceptions.InternalClientError(
505- ' no codec for composite attribute type {}' .format(
506- typoid))
489+ f' no codec for composite attribute type {typoid}' )
490+ if elem_codec.format is PG_FORMAT_TEXT:
491+ has_text_elements = True
507492 comp_elem_codecs.append(elem_codec)
508493
509494 element_names = collections.OrderedDict()
510495 for i, attrname in enumerate (ti[' attrnames' ]):
511496 element_names[attrname] = i
512497
498+ # If at least one element is text-encoded, we must
499+ # encode the whole composite as text.
513500 if has_text_elements:
514- format = PG_FORMAT_TEXT
501+ elem_format = PG_FORMAT_TEXT
502+ else :
503+ elem_format = PG_FORMAT_BINARY
515504
516- self ._derived_type_codecs[oid, format ] = \
505+ self ._derived_type_codecs[oid, elem_format ] = \
517506 Codec.new_composite_codec(
518- oid, name, schema, format , comp_elem_codecs,
507+ oid, name, schema, elem_format , comp_elem_codecs,
519508 comp_type_attrs, element_names)
520509
521510 elif ti[' kind' ] == b' d' :
522511 # Domain type
523512
524513 if not base_type:
525514 raise exceptions.InternalClientError(
526- ' type record missing base type for domain {}' .format(
527- oid))
515+ f' type record missing base type for domain {oid}' )
528516
529- elem_codec = self .get_codec(base_type, format )
517+ elem_codec = self .get_codec(base_type, PG_FORMAT_ANY )
530518 if elem_codec is None :
531- format = PG_FORMAT_TEXT
532519 elem_codec = self .declare_fallback_codec(
533- base_type, name , schema)
520+ base_type, ti[ ' basetype_name ' ] , schema)
534521
535- self ._derived_type_codecs[oid, format] = elem_codec
522+ self ._derived_type_codecs[oid, elem_codec. format] = elem_codec
536523
537524 elif ti[' kind' ] == b' r' :
538525 # Range type
539526
540527 if not range_subtype_oid:
541528 raise exceptions.InternalClientError(
542- ' type record missing base type for range {}' .format(
543- oid))
529+ f' type record missing base type for range {oid}' )
544530
545- if ti[' elem_has_bin_io' ]:
546- elem_format = PG_FORMAT_BINARY
547- else :
548- elem_format = PG_FORMAT_TEXT
549-
550- elem_codec = self .get_codec(range_subtype_oid, elem_format)
531+ elem_codec = self .get_codec(range_subtype_oid, PG_FORMAT_ANY)
551532 if elem_codec is None :
552- elem_format = PG_FORMAT_TEXT
553533 elem_codec = self .declare_fallback_codec(
554- range_subtype_oid, name , schema)
534+ range_subtype_oid, ti[ ' range_subtype_name ' ] , schema)
555535
556- self ._derived_type_codecs[oid, elem_format ] = \
536+ self ._derived_type_codecs[oid, elem_codec.format ] = \
557537 Codec.new_range_codec(oid, name, schema, elem_codec)
558538
559539 elif ti[' kind' ] == b' e' :
@@ -665,10 +645,6 @@ cdef class DataCodecConfig:
665645 def declare_fallback_codec (self , uint32_t oid , str name , str schema ):
666646 cdef Codec codec
667647
668- codec = self .get_codec(oid, PG_FORMAT_TEXT)
669- if codec is not None :
670- return codec
671-
672648 if oid <= MAXBUILTINOID:
673649 # This is a BKI type, for which asyncpg has no
674650 # defined codec. This should only happen for newly
@@ -695,34 +671,49 @@ cdef class DataCodecConfig:
695671 bint ignore_custom_codec = False ):
696672 cdef Codec codec
697673
698- if not ignore_custom_codec:
699- codec = self .get_any_local_codec(oid)
700- if codec is not None :
701- if codec.format != format:
702- # The codec for this OID has been overridden by
703- # set_{builtin}_type_codec with a different format.
704- # We must respect that and not return a core codec.
705- return None
706- else :
707- return codec
708-
709- codec = get_core_codec(oid, format)
710- if codec is not None :
674+ if format == PG_FORMAT_ANY:
675+ codec = self .get_codec(
676+ oid, PG_FORMAT_BINARY, ignore_custom_codec)
677+ if codec is None :
678+ codec = self .get_codec(
679+ oid, PG_FORMAT_TEXT, ignore_custom_codec)
711680 return codec
712681 else :
713- try :
714- return self ._derived_type_codecs[oid, format]
715- except KeyError :
716- return None
682+ if not ignore_custom_codec:
683+ codec = self .get_custom_codec(oid, PG_FORMAT_ANY)
684+ if codec is not None :
685+ if codec.format != format:
686+ # The codec for this OID has been overridden by
687+ # set_{builtin}_type_codec with a different format.
688+ # We must respect that and not return a core codec.
689+ return None
690+ else :
691+ return codec
692+
693+ codec = get_core_codec(oid, format)
694+ if codec is not None :
695+ return codec
696+ else :
697+ try :
698+ return self ._derived_type_codecs[oid, format]
699+ except KeyError :
700+ return None
717701
718- cdef inline Codec get_any_local_codec(self , uint32_t oid):
702+ cdef inline Codec get_custom_codec(
703+ self ,
704+ uint32_t oid,
705+ ServerDataFormat format
706+ ):
719707 cdef Codec codec
720708
721- codec = self ._custom_type_codecs.get((oid, PG_FORMAT_BINARY))
722- if codec is None :
723- return self ._custom_type_codecs.get((oid, PG_FORMAT_TEXT))
709+ if format == PG_FORMAT_ANY:
710+ codec = self .get_custom_codec(oid, PG_FORMAT_BINARY)
711+ if codec is None :
712+ codec = self .get_custom_codec(oid, PG_FORMAT_TEXT)
724713 else :
725- return codec
714+ codec = self ._custom_type_codecs.get((oid, format))
715+
716+ return codec
726717
727718
728719cdef inline Codec get_core_codec(
0 commit comments