@@ -440,14 +440,7 @@ cdef class DataCodecConfig:
440
440
for ti in types:
441
441
oid = ti[' oid' ]
442
442
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 :
451
444
continue
452
445
453
446
name = ti[' name' ]
@@ -468,92 +461,79 @@ cdef class DataCodecConfig:
468
461
name = name[1 :]
469
462
name = ' {}[]' .format(name)
470
463
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)
477
465
if elem_codec is None :
478
- elem_format = PG_FORMAT_TEXT
479
466
elem_codec = self .declare_fallback_codec(
480
- array_element_oid, name , schema)
467
+ array_element_oid, ti[ ' elemtype_name ' ] , schema)
481
468
482
469
elem_delim = < Py_UCS4> ti[' elemdelim' ][0 ]
483
470
484
- self ._derived_type_codecs[oid, elem_format ] = \
471
+ self ._derived_type_codecs[oid, elem_codec.format ] = \
485
472
Codec.new_array_codec(
486
473
oid, name, schema, elem_codec, elem_delim)
487
474
488
475
elif ti[' kind' ] == b' c' :
476
+ # Composite type
477
+
489
478
if not comp_type_attrs:
490
479
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}' )
495
481
496
482
comp_elem_codecs = []
483
+ has_text_elements = False
497
484
498
485
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)
503
487
if elem_codec is None :
504
488
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
507
492
comp_elem_codecs.append(elem_codec)
508
493
509
494
element_names = collections.OrderedDict()
510
495
for i, attrname in enumerate (ti[' attrnames' ]):
511
496
element_names[attrname] = i
512
497
498
+ # If at least one element is text-encoded, we must
499
+ # encode the whole composite as text.
513
500
if has_text_elements:
514
- format = PG_FORMAT_TEXT
501
+ elem_format = PG_FORMAT_TEXT
502
+ else :
503
+ elem_format = PG_FORMAT_BINARY
515
504
516
- self ._derived_type_codecs[oid, format ] = \
505
+ self ._derived_type_codecs[oid, elem_format ] = \
517
506
Codec.new_composite_codec(
518
- oid, name, schema, format , comp_elem_codecs,
507
+ oid, name, schema, elem_format , comp_elem_codecs,
519
508
comp_type_attrs, element_names)
520
509
521
510
elif ti[' kind' ] == b' d' :
522
511
# Domain type
523
512
524
513
if not base_type:
525
514
raise exceptions.InternalClientError(
526
- ' type record missing base type for domain {}' .format(
527
- oid))
515
+ f' type record missing base type for domain {oid}' )
528
516
529
- elem_codec = self .get_codec(base_type, format )
517
+ elem_codec = self .get_codec(base_type, PG_FORMAT_ANY )
530
518
if elem_codec is None :
531
- format = PG_FORMAT_TEXT
532
519
elem_codec = self .declare_fallback_codec(
533
- base_type, name , schema)
520
+ base_type, ti[ ' basetype_name ' ] , schema)
534
521
535
- self ._derived_type_codecs[oid, format] = elem_codec
522
+ self ._derived_type_codecs[oid, elem_codec. format] = elem_codec
536
523
537
524
elif ti[' kind' ] == b' r' :
538
525
# Range type
539
526
540
527
if not range_subtype_oid:
541
528
raise exceptions.InternalClientError(
542
- ' type record missing base type for range {}' .format(
543
- oid))
529
+ f' type record missing base type for range {oid}' )
544
530
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)
551
532
if elem_codec is None :
552
- elem_format = PG_FORMAT_TEXT
553
533
elem_codec = self .declare_fallback_codec(
554
- range_subtype_oid, name , schema)
534
+ range_subtype_oid, ti[ ' range_subtype_name ' ] , schema)
555
535
556
- self ._derived_type_codecs[oid, elem_format ] = \
536
+ self ._derived_type_codecs[oid, elem_codec.format ] = \
557
537
Codec.new_range_codec(oid, name, schema, elem_codec)
558
538
559
539
elif ti[' kind' ] == b' e' :
@@ -665,10 +645,6 @@ cdef class DataCodecConfig:
665
645
def declare_fallback_codec (self , uint32_t oid , str name , str schema ):
666
646
cdef Codec codec
667
647
668
- codec = self .get_codec(oid, PG_FORMAT_TEXT)
669
- if codec is not None :
670
- return codec
671
-
672
648
if oid <= MAXBUILTINOID:
673
649
# This is a BKI type, for which asyncpg has no
674
650
# defined codec. This should only happen for newly
@@ -696,34 +672,49 @@ cdef class DataCodecConfig:
696
672
bint ignore_custom_codec = False ):
697
673
cdef Codec codec
698
674
699
- if not ignore_custom_codec:
700
- codec = self .get_any_local_codec(oid)
701
- if codec is not None :
702
- if codec.format != format:
703
- # The codec for this OID has been overridden by
704
- # set_{builtin}_type_codec with a different format.
705
- # We must respect that and not return a core codec.
706
- return None
707
- else :
708
- return codec
709
-
710
- codec = get_core_codec(oid, format)
711
- if codec is not None :
675
+ if format == PG_FORMAT_ANY:
676
+ codec = self .get_codec(
677
+ oid, PG_FORMAT_BINARY, ignore_custom_codec)
678
+ if codec is None :
679
+ codec = self .get_codec(
680
+ oid, PG_FORMAT_TEXT, ignore_custom_codec)
712
681
return codec
713
682
else :
714
- try :
715
- return self ._derived_type_codecs[oid, format]
716
- except KeyError :
717
- return None
683
+ if not ignore_custom_codec:
684
+ codec = self .get_custom_codec(oid, PG_FORMAT_ANY)
685
+ if codec is not None :
686
+ if codec.format != format:
687
+ # The codec for this OID has been overridden by
688
+ # set_{builtin}_type_codec with a different format.
689
+ # We must respect that and not return a core codec.
690
+ return None
691
+ else :
692
+ return codec
693
+
694
+ codec = get_core_codec(oid, format)
695
+ if codec is not None :
696
+ return codec
697
+ else :
698
+ try :
699
+ return self ._derived_type_codecs[oid, format]
700
+ except KeyError :
701
+ return None
718
702
719
- cdef inline Codec get_any_local_codec(self , uint32_t oid):
703
+ cdef inline Codec get_custom_codec(
704
+ self ,
705
+ uint32_t oid,
706
+ ServerDataFormat format
707
+ ):
720
708
cdef Codec codec
721
709
722
- codec = self ._custom_type_codecs.get((oid, PG_FORMAT_BINARY))
723
- if codec is None :
724
- return self ._custom_type_codecs.get((oid, PG_FORMAT_TEXT))
710
+ if format == PG_FORMAT_ANY:
711
+ codec = self .get_custom_codec(oid, PG_FORMAT_BINARY)
712
+ if codec is None :
713
+ codec = self .get_custom_codec(oid, PG_FORMAT_TEXT)
725
714
else :
726
- return codec
715
+ codec = self ._custom_type_codecs.get((oid, format))
716
+
717
+ return codec
727
718
728
719
729
720
cdef inline Codec get_core_codec(
0 commit comments