duckdb / duckdb/duckdb-python

UHUGEINT values>= 2^127 return negative w/ to_arrow_table

Aperta
#568 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
needs triage
Lingua principale
Python
Stelle
187
Fork
112
Merge medio
13h 29m
PR unite (30g)
17

Descrizione

### What happens?

When a `UHUGEINT` column is exported to Arrow, values >= 2^127 come back negative, yet fetchall returns the correct value.

`UHUGEINT` is exported as `decimal128(38, 0)`, and that schema misdescribes both the data's signedness and precision.

pyarrow properly raises an error in the same case.

See the `Decimal('-1')` in the output below for the error:
>
> ============ SELECT ~(0::UHUGEINT) AS v ==========
> con.execute(sql).fetchall()=[(340282366920938463463374607431768211455,)]
> con.sql(sql).to_arrow_table().to_pylist()=[{'v': Decimal('-1')}]
> ============ SELECT 340282366920938463463374607431768211455 AS v ==========
> con.execute(sql).fetchall()=[(340282366920938463463374607431768211455,)]
> con.sql(sql).to_arrow_table().to_pylist()=[{'v': Decimal('-1')}]
> ============ pyarrow representability ==========
> val=340282366920938463463374607431768211455
> decimal128(38, 0) -> ArrowInvalid: Decimal type with precision 39 does not fit into precision inferred from first array element: 38
> pa.array([decimal.Decimal(val)], pa.decimal256(39, 0)).to_pylist()=[Decimal('340282366920938463463374607431768211455')]

### To Reproduce

```py
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = ["duckdb==1.5.5", "pyarrow>=22"]
# ///
import decimal

import duckdb
import pyarrow as pa

con = duckdb.connect()
sql = "SELECT ~(0::UHUGEINT) AS v" # all 128 bits set, i.e. UHUGEINT max

# Test 1
print("============", sql, "==========")
print(f"{con.execute(sql).fetchall()=}")
print(f"{con.sql(sql).to_arrow_table().to_pylist()=}")

# Test 2
val = 2**128-1
sql = f"SELECT {val} AS v"
print("============", sql, "==========")
print(f"{con.execute(sql).fetchall()=}")
print(f"{con.sql(sql).to_arrow_table().to_pylist()=}")

# Test 3: Arrow can represent this value, just not as decimal128(38, 0)
val = 2**128-1
print("============ pyarrow representability ==========")
print(f"{val=}")
try:
print(f"{pa.array([decimal.Decimal(val)], pa.decimal128(38, 0))=}")
except Exception as e:
print(f"decimal128(38, 0) -> {type(e).__name__}: {e}")
print(f"{pa.array([decimal.Decimal(val)], pa.decimal256(39, 0)).to_pylist()=}")
```

### OS:

Linux

### DuckDB Package Version:

1.5.5 and 1.6.0.dev341

### Python Version:

3.14

### Full Name:

Paul T

### Affiliation:

Iqmo

### What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.

I have tested with a nightly build

### Did you include all relevant data sets for reproducing the issue?

Yes

### Did you include all code required to reproduce the issue?

- [x] Yes, I have

### Did you include all relevant configuration to reproduce the issue?

- [x] Yes, I have

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia con lo script di riproduzione Python fornito e segui il punto di ingresso `to_arrow_table()` per i valori `UHUGEINT`. Verifica lo schema Arrow e il comportamento di andata e ritorno per i valori pari o superiori a 2^127, incluso il valore massimo; il lavoro è completato quando non vengono più restituiti come negativi e sono rappresentati con precisione e segno sufficienti.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
databases
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
55/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.