Description
- asyncpg version: 0.11
- PostgreSQL version: 9.6
- Python version: 3.6
- Platform: Windows
- Do you use pgbouncer?: No
- Did you install asyncpg with pip?: Yes
- If you built asyncpg locally, which version of Cython did you use?: N/A
- Can the issue be reproduced under both asyncio and
uvloop?: Yes
I have no clue if this is a limitation of the COPY
protocol, if so sorry for the issue.
My problem comes from attempting to insert elements using None
to denote NULL
. For example, given the following table:
CREATE TABLE test (id SERIAL PRIMARY KEY, entity_id INTEGER);
Attempts to create a connection and insert NULL
entity_id entries results in a TypeError
:
async with pool.acquire() as con:
await con.copy_records_to_table('test', records=[(1, 1), (2, None)],
columns=('id', 'entity_id'))
Would result in:
Traceback (most recent call last):
File "asyncpg\connection.py", line 619, in copy_records_to_table
copy_stmt, records, intro_ps._state, timeout)
File "asyncpg\connection.py", line 741, in _copy_in_records
copy_stmt, None, None, records, intro_stmt, timeout)
File "asyncpg\protocol\protocol.pyx", line 441, in copy_in (asyncpg/protocol/protocol.c:66206)
File "asyncpg\protocol\protocol.pyx", line 389, in asyncpg.protocol.protocol.BaseProtocol.copy_in (asyncpg/protocol/protocol.c:64677)
File "asyncpg\protocol\codecs\base.pyx", line 150, in asyncpg.protocol.protocol.Codec.encode (asyncpg/protocol/protocol.c:14433)
File "asyncpg\protocol\codecs\base.pyx", line 95, in asyncpg.protocol.protocol.Codec.encode_scalar (asyncpg/protocol/protocol.c:13818)
File "asyncpg\protocol\codecs\int.pyx", line 47, in asyncpg.protocol.protocol.int8_encode (asyncpg/protocol/protocol.c:29584)
TypeError: an integer is required (got type NoneType)
The documentation for the COPY
protocol seems to suggest that encoding into NULL
is possible:
Each tuple begins with a 16-bit integer count of the number of fields in the tuple. (Presently, all tuples in a table will have the same count, but that might not always be true.) Then, repeated for each field in the tuple, there is a 32-bit length word followed by that many bytes of field data. (The length word does not include itself, and can be zero.) As a special case, -1 indicates a NULL field value. No value bytes follow in the NULL case.
Emphasis mine, from the documentation.
However I don't know if I'm misreading it.
Thanks for your time.