Skip to content

Commit df64f55

Browse files
elprans1st1
authored andcommitted
Fix erroneous codec cache invalidation on internal codec aliasing.
set_builtin_type_codec() flushes the codec cache, so internal codec aliasing (for enums and fallback) must use a version that doesn't kill the cache. Fixes: #133, #122.
1 parent ffb8959 commit df64f55

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

asyncpg/protocol/codecs/base.pyx

+12-4
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,10 @@ cdef class DataCodecConfig:
468468
self._type_codecs_cache[oid, elem_format] = \
469469
Codec.new_range_codec(oid, name, schema, elem_codec)
470470

471+
elif ti['kind'] == b'e':
472+
# Enum types are essentially text
473+
self._set_builtin_type_codec(oid, name, schema, 'scalar',
474+
TEXTOID, PG_FORMAT_ANY)
471475
else:
472476
self.declare_fallback_codec(oid, name, schema)
473477

@@ -481,8 +485,8 @@ cdef class DataCodecConfig:
481485

482486
self.clear_type_cache()
483487

484-
def set_builtin_type_codec(self, typeoid, typename, typeschema, typekind,
485-
alias_to, format=PG_FORMAT_ANY):
488+
def _set_builtin_type_codec(self, typeoid, typename, typeschema, typekind,
489+
alias_to, format=PG_FORMAT_ANY):
486490
cdef:
487491
Codec codec
488492
Codec target_codec
@@ -517,6 +521,10 @@ cdef class DataCodecConfig:
517521
(typeoid, PG_FORMAT_TEXT) not in self._local_type_codecs):
518522
raise ValueError('unknown alias target: {}'.format(alias_to))
519523

524+
def set_builtin_type_codec(self, typeoid, typename, typeschema, typekind,
525+
alias_to, format=PG_FORMAT_ANY):
526+
self._set_builtin_type_codec(typeoid, typename, typeschema, typekind,
527+
alias_to, format)
520528
self.clear_type_cache()
521529

522530
def clear_type_cache(self):
@@ -545,8 +553,8 @@ cdef class DataCodecConfig:
545553
# can avoid this by specifying a codec for this type
546554
# using Connection.set_type_codec().
547555
#
548-
self.set_builtin_type_codec(oid, name, schema, 'scalar',
549-
TEXTOID, PG_FORMAT_TEXT)
556+
self._set_builtin_type_codec(oid, name, schema, 'scalar',
557+
TEXTOID, PG_FORMAT_TEXT)
550558

551559
codec = self.get_codec(oid, PG_FORMAT_TEXT)
552560

tests/test_codecs.py

+35-7
Original file line numberDiff line numberDiff line change
@@ -1166,15 +1166,43 @@ async def test_enum_in_array(self):
11661166
await self.con.execute('''
11671167
CREATE TYPE enum_t AS ENUM ('abc', 'def', 'ghi');
11681168
''')
1169-
result = await self.con.fetchrow('''SELECT $1::enum_t[];''',
1170-
['abc'])
1171-
self.assertEqual(result, (['abc'],))
11721169

1173-
result = await self.con.fetchrow('''SELECT ARRAY[$1::enum_t];''',
1174-
'abc')
1170+
try:
1171+
result = await self.con.fetchrow('''SELECT $1::enum_t[];''',
1172+
['abc'])
1173+
self.assertEqual(result, (['abc'],))
1174+
1175+
result = await self.con.fetchrow('''SELECT ARRAY[$1::enum_t];''',
1176+
'abc')
1177+
1178+
self.assertEqual(result, (['abc'],))
11751179

1176-
self.assertEqual(result, (['abc'],))
1180+
finally:
1181+
await self.con.execute('''
1182+
DROP TYPE enum_t;
1183+
''')
11771184

1185+
async def test_enum_and_range(self):
11781186
await self.con.execute('''
1179-
DROP TYPE enum_t;
1187+
CREATE TYPE enum_t AS ENUM ('abc', 'def', 'ghi');
1188+
CREATE TABLE testtab (
1189+
a int4range,
1190+
b enum_t
1191+
);
1192+
1193+
INSERT INTO testtab VALUES (
1194+
'[10, 20)', 'abc'
1195+
);
11801196
''')
1197+
1198+
try:
1199+
result = await self.con.fetchrow('''
1200+
SELECT testtab.a FROM testtab WHERE testtab.b = $1
1201+
''', 'abc')
1202+
1203+
self.assertEqual(result, (asyncpg.Range(10, 20),))
1204+
finally:
1205+
await self.con.execute('''
1206+
DROP TABLE testtab;
1207+
DROP TYPE enum_t;
1208+
''')

0 commit comments

Comments
 (0)