asyncpg.exceptions.DataError: invalid input for query argument $1: 217027642536 (value out of int32 range)
asyncpg.exceptions.DataError: invalid input for query argument $1: 217027642536 (value out of int32 range)
我正在开发一个使用 FastAPI 以及 Pydantic 和 SQLAlchemy 的项目。我还使用 encode/databases 来管理数据库连接。但是出于某种奇怪的原因,每当我尝试保存到数据库时,我都会得到 asyncpg.exceptions.DataError: invalid input for query argument : 217027642536 (value out of int32 range)
。这是我的代码的样子:
database.py
...
...
currencies = Table(
'currencies',
metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('price', Float),
Column('price_date', DateTime),
Column('price_timestamp', DateTime),
Column('market_cap', Integer)
)
database = Database(DATABASE_URL)
database_manager.py
...
...
async def add_currency(payload: Currency):
query = currencies.insert().values(**payload.dict())
return await database.execute(query=query)
endpoints.py
...
...
@endpoints.post('/', response_model=CurrencyOutput, status_code=201)
async def add_currency():
data = check_currency_price()
payload = Currency(
name=data['name'],
price=data['price'],
price_date=data['price_date'],
price_timestamp=data['price_timestamp'],
market_cap=data['market_cap']
)
currency_id = await database_manager.add_currency(payload)
response = {
'id': currency_id,
**payload.dict()
}
return response
models.py
...
...
class Currency(BaseModel):
name: str
price: float
price_date: datetime
price_timestamp: datetime
market_cap: int
class CurrencyOutput(Currency):
id: int
services.py
def check_currency_price():
response = httpx.get(
'https://api.nomics.com/v1/currencies/ticker?' +
'key=somerandomAPIkey&ids=BTC&interval=1d,30d&convert=USD'
)
return response.json()[0]
我看不出这有什么问题。有人,请告诉我这到底是怎么回事?
你基本上有整数溢出,Int32 代表 2^31 - 1
,这意味着它可以存储范围 -2147483648 到 2147483648 但您尝试插入的值大于 2^31
2**31 > 217027642536
Out: False
所以你需要使用 SQLAlchemy 的 BigInteger 类型表示 Int64 它也表示 2^63 - 1
可以存储范围内的值消极和积极 9,223,372,036,854,775,807
from sqlalchemy import BigInteger
currencies = Table(
'currencies',
metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('price', Float),
Column('price_date', DateTime),
Column('price_timestamp', DateTime),
Column('market_cap', BigInteger)
) ^^^^^^^^^^
使用 BigInteger 更改市场的列类型应该可以解决问题,但要注意更大的类型会占用更多内存。
我正在开发一个使用 FastAPI 以及 Pydantic 和 SQLAlchemy 的项目。我还使用 encode/databases 来管理数据库连接。但是出于某种奇怪的原因,每当我尝试保存到数据库时,我都会得到 asyncpg.exceptions.DataError: invalid input for query argument : 217027642536 (value out of int32 range)
。这是我的代码的样子:
database.py
...
...
currencies = Table(
'currencies',
metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('price', Float),
Column('price_date', DateTime),
Column('price_timestamp', DateTime),
Column('market_cap', Integer)
)
database = Database(DATABASE_URL)
database_manager.py
...
...
async def add_currency(payload: Currency):
query = currencies.insert().values(**payload.dict())
return await database.execute(query=query)
endpoints.py
...
...
@endpoints.post('/', response_model=CurrencyOutput, status_code=201)
async def add_currency():
data = check_currency_price()
payload = Currency(
name=data['name'],
price=data['price'],
price_date=data['price_date'],
price_timestamp=data['price_timestamp'],
market_cap=data['market_cap']
)
currency_id = await database_manager.add_currency(payload)
response = {
'id': currency_id,
**payload.dict()
}
return response
models.py
...
...
class Currency(BaseModel):
name: str
price: float
price_date: datetime
price_timestamp: datetime
market_cap: int
class CurrencyOutput(Currency):
id: int
services.py
def check_currency_price():
response = httpx.get(
'https://api.nomics.com/v1/currencies/ticker?' +
'key=somerandomAPIkey&ids=BTC&interval=1d,30d&convert=USD'
)
return response.json()[0]
我看不出这有什么问题。有人,请告诉我这到底是怎么回事?
你基本上有整数溢出,Int32 代表 2^31 - 1
,这意味着它可以存储范围 -2147483648 到 2147483648 但您尝试插入的值大于 2^31
2**31 > 217027642536
Out: False
所以你需要使用 SQLAlchemy 的 BigInteger 类型表示 Int64 它也表示 2^63 - 1
可以存储范围内的值消极和积极 9,223,372,036,854,775,807
from sqlalchemy import BigInteger
currencies = Table(
'currencies',
metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('price', Float),
Column('price_date', DateTime),
Column('price_timestamp', DateTime),
Column('market_cap', BigInteger)
) ^^^^^^^^^^
使用 BigInteger 更改市场的列类型应该可以解决问题,但要注意更大的类型会占用更多内存。