SurrealDB stores a plain number as a 64-bit int, a 64-bit float or a decimal. SurrealDB 4.0 adds sized integers and floats, such as u8 and f32, and bigdecimal, a decimal with no fixed limit on its digits. This page documents the Python classes for the SurrealDB 4.0 number types, and the limits of a plain int and a Decimal.
from surrealdb import (
F16, F32, I8, I16, I32, U8, U16, U32, U64,
BigDecimal, SizedFloat, SizedInt,
)Source: sized.py, big_decimal.py
Plain numbers
| Python | SurrealDB | Read back as |
|---|---|---|
int | int | int |
float | float | float |
decimal.Decimal | decimal | Decimal |
SurrealDB stores an int as a signed 64-bit integer, from -9223372036854775808 to 9223372036854775807. The SDK raises ValueError for an int outside that range before anything is sent, because the server would store a different number. For a larger whole number, send a Decimal, or a U64 up to 18446744073709551615.
A SurrealDB decimal holds up to 28 digits after the decimal point, and the server rounds a value with more. SurrealDB 3.0 and later also drop trailing zeros, so Decimal("19.90") reads back as Decimal('19.9'). The SDK sends a Decimal in plain notation, such as 0.0000001 rather than 1E-7.
from decimal import Decimal
from surrealdb import Surreal
with Surreal("ws://localhost:8000") as db:
db.signin({"username": "root", "password": "secret"})
db.use("surrealdb", "docs")
values = {"price": Decimal("19.90"), "rate": Decimal("1E-29")}
print(db.query("RETURN [$price, $rate]", values).first())[Decimal('19.9'), Decimal('0')]The rate has 29 digits after the point, so the server rounds it to zero. For more digits, or to keep trailing zeros, use a BigDecimal with SurrealDB 4.0.
Sized numbers
Each sized number class is a subclass of int or float for one SurrealDB 4.0 number type. It refuses a value outside the range of its type when it is made.
| Class | SurrealDB type | Values |
|---|---|---|
I8 | i8 | -128 to 127 |
U8 | u8 | 0 to 255 |
I16 | i16 | -32768 to 32767 |
U16 | u16 | 0 to 65535 |
I32 | i32 | -2147483648 to 2147483647 |
U32 | u32 | 0 to 4294967295 |
U64 | u64 | 0 to 18446744073709551615 |
F16 | f16 | Half-precision floats, up to 65504 |
F32 | f32 | Single-precision floats |
I8(value=0)
F32(value=0.0)Parameter | Type | Description |
|---|---|---|
value | int | float | str | The number, as for int()or float(). Defaults to 0. An integer class also takes a floatwith no fraction, such as 2.0. |
An integer class raises ValueError for a value outside its range or a value with a fraction. Each integer class has MIN and MAX class attributes that give its range. F16 and F32 round the value to the nearest number of their width, as a cast to that width does, and raise ValueError for a finite value that is too large for the width.
print(F32(1.1), F16(1.1))
print(U8.MIN, U8.MAX)
print(I8(5) == 5, type(I8(5) + 1).__name__)F32(1.100000023841858) F16(1.099609375)
0 255
True intI8(200)ValueError: 200 is outside the I8 range (-128 to 127); use a wider kind or a plain intA sized number works anywhere a number does. I8(5) == 5 is true, and arithmetic gives back a plain int or float, so compare type() to tell a sized number from a plain one. SizedInt and SizedFloat are the base classes, for isinstance() checks; construct one of the subclasses. str() gives the same text as repr(), such as I8(5), so pass int(value) or float(value) to format the number alone.
Sending and reading sized numbers
Over cbor.2, which SurrealDB 4.0 servers speak, a sized number is sent as its own type and reads back as the same class. A field defined with a sized type also stores a plain int that fits as that type. Servers before 4.0 speak plain cbor, which has no sized types, so the SDK sends the nearest type that the server has.
| Python | Over cbor.2 (SurrealDB 4.0) | Over cbor (earlier servers) |
|---|---|---|
I8, U8, I16, U16, I32, U32 | Their own type, read back as the same class | int, read back as int |
U64 | u64, read back as U64 | int, or decimal above 9223372036854775807, read back as int or Decimal |
F16, F32 | Their own type, read back as the same class | float, read back as float |
db.wire_format tells you which format a connection uses. This example needs SurrealDB 4.0:
from surrealdb import F32, RecordID, Surreal
with Surreal("ws://localhost:8000") as db:
db.signin({"username": "root", "password": "secret"})
db.use("surrealdb", "docs")
db.query("DEFINE FIELD age ON person TYPE u8").execute()
person = db.create(RecordID("person", "tobie"), {
"age": 30,
"score": F32(0.1),
})
print(person["age"], person["score"])U8(30) F32(0.10000000149011612) BigDecimal
A BigDecimal is a decimal.Decimal that SurrealDB 4.0 stores as a bigdecimal rather than a decimal. A bigdecimal holds up to 131072 digits before the decimal point and 16383 after it, and keeps its scale as written, so BigDecimal("1.50") keeps its trailing zero.
BigDecimal(value="0", context=None)Parameter | Type | Description |
|---|---|---|
value | Decimal | int | float | str | The number, as for Decimal(). Defaults to "0". |
context | decimal.Context | None | The decimalcontext to build the value with. |
The constructor raises ValueError for text that is not a number, for NaN or an infinity, and for a value with more digits than a bigdecimal holds.
from surrealdb import BigDecimal
price = BigDecimal("1.50")
print(repr(price), price == BigDecimal("1.5"))
print(repr(price * 2))BigDecimal('1.50') True
Decimal('3.00')A BigDecimal is a Decimal in every other way. Values that differ only in scale are equal, and arithmetic gives back a plain Decimal, rounded to the precision of the current decimal context: 28 significant digits by default. To calculate with larger numbers, raise decimal.getcontext().prec, and wrap the result in BigDecimal to send it as a bigdecimal.
Sending and reading big decimals
Over cbor.2 (SurrealDB 4.0) | Over cbor (earlier servers) |
|---|---|
bigdecimal with its scale, read back as BigDecimal | decimal when the value fits one, read back as Decimal; otherwise its text as a string, read back as str |
See also
Python values for every value class
Value types for how every value converts
Numbers in SurrealQL, including sized numbers and big decimals