Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion asyncpg/protocol/codecs/array.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -858,8 +858,17 @@ cdef arraytext_decode(ConnectionSettings settings, FRBuffer *buf):
return array_decode(settings, buf, <decode_func_ex>&text_decode_ex, NULL)


cdef arrayvarchar_encode(ConnectionSettings settings, WriteBuffer buf, items):
array_encode(settings, buf, items, VARCHAROID,
<encode_func_ex>&text_encode_ex, NULL)


cdef arrayvarchar_decode(ConnectionSettings settings, FRBuffer *buf):
return array_decode(settings, buf, <decode_func_ex>&text_decode_ex, NULL)


cdef init_array_codecs():
# oid[] and text[] are registered as core codecs
# oid[], text[], and varchar[] are registered as core codecs
# to make type introspection query work
#
register_core_codec(_OIDOID,
Expand All @@ -872,4 +881,9 @@ cdef init_array_codecs():
<decode_func>&arraytext_decode,
PG_FORMAT_BINARY)

register_core_codec(_VARCHAROID,
<encode_func>&arrayvarchar_encode,
<decode_func>&arrayvarchar_decode,
PG_FORMAT_BINARY)

init_array_codecs()
6 changes: 4 additions & 2 deletions asyncpg/protocol/pgtypes.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ DEF MONEYOID = 790
DEF MACADDROID = 829
DEF INETOID = 869
DEF _TEXTOID = 1009
DEF _VARCHAROID = 1015
DEF _OIDOID = 1028
DEF ACLITEMOID = 1033
DEF BPCHAROID = 1042
Expand Down Expand Up @@ -113,7 +114,7 @@ DEF ANYCOMPATIBLEARRAYOID = 5078
DEF ANYCOMPATIBLENONARRAYOID = 5079
DEF ANYCOMPATIBLERANGEOID = 5080

ARRAY_TYPES = {_TEXTOID, _OIDOID}
ARRAY_TYPES = {_TEXTOID, _VARCHAROID, _OIDOID}

BUILTIN_TYPE_OID_MAP = {
ABSTIMEOID: 'abstime',
Expand Down Expand Up @@ -215,7 +216,8 @@ BUILTIN_TYPE_OID_MAP = {
XIDOID: 'xid',
XMLOID: 'xml',
_OIDOID: 'oid[]',
_TEXTOID: 'text[]'
_TEXTOID: 'text[]',
_VARCHAROID: 'varchar[]'
}

BUILTIN_TYPE_NAME_MAP = {v: k for k, v in BUILTIN_TYPE_OID_MAP.items()}
Expand Down
32 changes: 32 additions & 0 deletions tests/test_introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ async def _introspect_types(self, *args, **kwargs):
return await super()._introspect_types(*args, **kwargs)


class CountingIntrospectionConnection(apg_con.Connection):
"""Connection class to assert when type introspection is skipped."""
introspect_count = 0

async def _introspect_types(self, *args, **kwargs):
self.introspect_count += 1
return await super()._introspect_types(*args, **kwargs)


class TestIntrospection(tb.ConnectedTestCase):
@classmethod
def setUpClass(cls):
Expand Down Expand Up @@ -78,6 +87,29 @@ async def test_introspection_on_large_db(self):
with self.assertRunUnder(MAX_RUNTIME):
await self.con.fetchval('SELECT $1::int[]', [1, 2])

async def test_varchar_array_does_not_introspect(self):
conn = await self.connect(
connection_class=CountingIntrospectionConnection)
try:
cases = [
['a', 'b'],
[None, 'b'],
[],
[['a', 'b'], ['c', 'd']],
]

for case in cases:
result = await conn.fetchval('SELECT $1::varchar[]', case)
self.assertEqual(result, case)

result = await conn.fetchval(
"SELECT ARRAY['a', 'b']::varchar[]")
self.assertEqual(result, ['a', 'b'])

self.assertEqual(conn.introspect_count, 0)
finally:
await conn.close()

@tb.with_connection_options(statement_cache_size=0)
async def test_introspection_no_stmt_cache_01(self):
old_uid = apg_con._uid
Expand Down
2 changes: 1 addition & 1 deletion tools/generate_type_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# Array types with builtin codecs, necessary for codec
# bootstrap to work
#
_BUILTIN_ARRAYS = ('_text', '_oid')
_BUILTIN_ARRAYS = ('_text', '_varchar', '_oid')

_INVALIDOID = 0

Expand Down