Skip to content

Commit cddea9c

Browse files
fantixelprans
authored andcommitted
Added codec for built-in type tid
1 parent 7776b43 commit cddea9c

File tree

5 files changed

+96
-2
lines changed

5 files changed

+96
-2
lines changed

asyncpg/protocol/codecs/misc.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ cdef init_pseudo_codecs():
3131

3232
# OID and friends
3333
oid_types = [
34-
OIDOID, TIDOID, XIDOID, CIDOID
34+
OIDOID, XIDOID, CIDOID
3535
]
3636

3737
for oid_type in oid_types:

asyncpg/protocol/codecs/tid.pyx

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Copyright (C) 2016-present the asyncpg authors and contributors
2+
# <see AUTHORS file>
3+
#
4+
# This module is part of asyncpg and is released under
5+
# the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0
6+
7+
8+
cdef tid_encode(ConnectionSettings settings, WriteBuffer buf, obj):
9+
cdef int overflow = 0
10+
cdef long block, offset
11+
12+
if not (cpython.PyTuple_Check(obj) or cpython.PyList_Check(obj)):
13+
raise TypeError(
14+
'list or tuple expected (got type {})'.format(type(obj)))
15+
16+
if len(obj) != 2:
17+
raise ValueError(
18+
'invalid number of elements in tid tuple, expecting 2')
19+
20+
try:
21+
block = cpython.PyLong_AsLong(obj[0])
22+
except OverflowError:
23+
overflow = 1
24+
25+
# "long" and "long long" have the same size for x86_64, need an extra check
26+
if overflow or (sizeof(block) > 4 and (block < -2147483648 or
27+
block > 2147483647)):
28+
raise OverflowError(
29+
'block too big to be encoded as INT4: {!r}'.format(obj[0]))
30+
31+
try:
32+
offset = cpython.PyLong_AsLong(obj[1])
33+
overflow = 0
34+
except OverflowError:
35+
overflow = 1
36+
37+
if overflow or offset < -32768 or offset > 32767:
38+
raise OverflowError(
39+
'offset too big to be encoded as INT2: {!r}'.format(obj[1]))
40+
41+
buf.write_int32(6)
42+
buf.write_int32(<int32_t>block)
43+
buf.write_int16(<int16_t>offset)
44+
45+
46+
cdef tid_decode(ConnectionSettings settings, FastReadBuffer buf):
47+
cdef:
48+
int32_t block
49+
int16_t offset
50+
51+
block = hton.unpack_int32(buf.read(4))
52+
offset = hton.unpack_int16(buf.read(2))
53+
54+
return (block, offset)
55+
56+
57+
cdef init_tid_codecs():
58+
register_core_codec(TIDOID,
59+
<encode_func>&tid_encode,
60+
<decode_func>&tid_decode,
61+
PG_FORMAT_BINARY)
62+
63+
64+
init_tid_codecs()

asyncpg/protocol/protocol.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ include "codecs/json.pyx"
6666
include "codecs/money.pyx"
6767
include "codecs/network.pyx"
6868
include "codecs/numeric.pyx"
69+
include "codecs/tid.pyx"
6970
include "codecs/tsearch.pyx"
7071
include "codecs/txid.pyx"
7172
include "codecs/uuid.pyx"

docs/usage.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ The table below shows the correspondence between PostgreSQL and Python types.
152152
+----------------------+-----------------------------------------------------+
153153
| ``uuid`` | :class:`uuid.UUID <python:uuid.UUID>` |
154154
+----------------------+-----------------------------------------------------+
155+
| ``tid`` | :class:`tuple <python:tuple>` |
156+
+----------------------+-----------------------------------------------------+
155157

156158
All other types are encoded and decoded as text by default.
157159

tests/test_codecs.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ def _timezone(offset):
379379
('circle', 'circle', [
380380
asyncpg.Circle((0.0, 0.0), 100),
381381
]),
382+
('tid', 'tid', [
383+
(0, 2),
384+
]),
382385
]
383386

384387

@@ -598,7 +601,31 @@ async def test_invalid_input(self):
598601
]),
599602
('text', TypeError, 'expected str, got list', [
600603
[1]
601-
])
604+
]),
605+
('tid', TypeError, 'list or tuple expected', [
606+
b'foo'
607+
]),
608+
('tid', ValueError, 'invalid number of elements in tid tuple', [
609+
[],
610+
(),
611+
[1, 2, 3],
612+
(4,),
613+
]),
614+
('tid', OverflowError, 'block too big to be encoded as INT4', [
615+
(2**256, 0),
616+
(decimal.Decimal("2000000000000000000000000000000"), 0),
617+
(0xffffffff, 0),
618+
(2**31, 0),
619+
(-2**31 - 1, 0),
620+
]),
621+
('tid', OverflowError, 'offset too big to be encoded as INT2', [
622+
(0, 2**256),
623+
(0, decimal.Decimal("2000000000000000000000000000000")),
624+
(0, 0xffff),
625+
(0, 0xffffffff),
626+
(0, 32768),
627+
(0, -32769),
628+
]),
602629
]
603630

604631
for typname, errcls, errmsg, data in cases:

0 commit comments

Comments
 (0)