MagicStack / MagicStack/asyncpg

set_type_codec encoder to handle numpy/pandas null types not working with copy_records_to_table

Ouverte
#693 3 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Langage dominant
Python
Étoiles
8.1k
Forks
468
Métriques de merge des PR
Aucune PR mergée en 30 j

Description

* **asyncpg version**:0.21.0
* **PostgreSQL version**: PostgreSQL 13.1 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
* **Do you use a PostgreSQL SaaS? If so, which? Can you reproduce
the issue with a local PostgreSQL install?**:
* **Python version**: 3.7
* **Platform**: Ubuntu 18.04
* **Do you use pgbouncer?**: no
* **Did you install asyncpg with pip?**: yes
* **If you built asyncpg locally, which version of Cython did you use?**: -
* **Can the issue be reproduced under both asyncio and
[uvloop](https://github.com/magicstack/uvloop)?**: -

I am trying to set up an asyncpg in order to use ```copy_records_to_table``` method passing pandas data frame, converted to list of lists.

My table is simple:
```sql
create table sg.test("no" int4, dt timestmap)
```

As pandas/numpy have their own Null types for different types (pd.NaT for dates and np.nan for numerics) I tried to set up an appropriate encoder:

```python
import asyncio
import asyncpg
import pandas as pd
import numpy as np

data = [[1, np.datetime64('NaT')]]
df = pd.DataFrame(data=data, columns=["no", "dt"])

def encoder(val):
if isinstance(val, (type(pd.NaT), type(np.nan))):
return None
return bytes(val)

def decoder(val): # we do not need that for this task
return val

async def main(df: pd.DataFrame):

conn: asyncpg.Connection=await asyncpg.connect('postgresql://connection_string')

try:
await conn.set_type_codec(
'timestamp',
encoder=encoder,
decoder=decoder,
schema='pg_catalog',
format='binary'
)
res=await conn.copy_records_to_table('test', records=df.values.tolist(), columns=df.columns.values.tolist(), schema_name='sg')
print(res)
except ValueError as e:
print(e.args)
finally:
await conn.close()

asyncio.get_event_loop().run_until_complete(main(df))
```
I am getting following error:
```log
....
File "asyncpg/protocol/protocol.pyx", line 482, in copy_in
File "asyncpg/protocol/protocol.pyx", line 429, in asyncpg.protocol.protocol.BaseProtocol.copy_in
File "asyncpg/protocol/codecs/base.pyx", line 192, in asyncpg.protocol.protocol.Codec.encode
File "asyncpg/protocol/codecs/base.pyx", line 178, in asyncpg.protocol.protocol.Codec.encode_in_python
File "asyncpg/pgproto/./codecs/bytea.pyx", line 19, in asyncpg.pgproto.pgproto.bytea_encode
TypeError: a bytes-like object is required, not 'NoneType'
```

For me it is unclear what kind of bytes should ```encoder``` return in case of Null value, I have tried to investigate it backwards: select a null value from original table with custom decoder, but it seems that ```asyncpg``` just amends that method in case of null values at all. So it is still unclear what kind of data should be passed.

I have already tried to return following values at ```encoder```:
- ```b''```
- ```b'\x01'```
another error occurs:
```log
insufficient data left in message
````

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par les entrées de trace de pile de copy_in et Codec.encode dans asyncpg/protocol/protocol.pyx et asyncpg/protocol/codecs/base.pyx, puis examinez asyncpg/pgproto/./codecs/bytea.pyx. Reproduisez l’exemple de set_type_codec et copy_records_to_table avec des valeurs nulles de pandas et NumPy ; le travail est terminé lorsque le comportement nul attendu pour ce chemin est établi et couvert.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
numpy, pandas, postgresql, python
Domaine
databases
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
À clarifier
Accessibilité débutants
25/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.