Bucket ID
picopyn.bucket
Client-side bucket_id computation from Picodata's distribution key metadata.
Based on the Picodata "bucket_id calculation algorithm".
Each distribution key parameter is encoded as MessagePack, the encoded bytes are concatenated (in query meta order) and hashed with MurmurHash -- the same hash Picodata's own vshard-based sharding uses -- then reduced mod the tier's bucket count.
Supported distribution-key types
type_oid -- Picodata type -- expected Python value:
| OID | Picodata type | Python value |
|---|---|---|
| 16 | BOOLEAN |
bool |
| 20 | INTEGER (incl. UNSIGNED) |
int |
| 25 | TEXT/STRING/VARCHAR |
str |
| 701 | DOUBLE |
float |
| 1184 | DATETIME |
datetime.datetime (must be timezone-aware) |
| 1700 | DECIMAL |
decimal.Decimal (finite, at most 28 significant and 28 fractional digits) |
| 2950 | UUID |
uuid.UUID |
Note
DOUBLE accepts NaN/Infinity (hashed as their raw IEEE754 bytes, same as any other
float); DECIMAL doesn't -- non-finite Decimal values have no such raw encoding,
so they're rejected as an unsupported value. A DECIMAL is also rejected rather than
rounded once it exceeds either of the two limits a bind parameter is subject to --
28 significant digits or 28 fractional ones -- since we can't be sure the computed
bucket_id would then match the server's.
Picodata currently calculates DECIMAL bucket IDs differently depending on the
pgwire parameter format. Binary NUMERIC expands a positive exponent (1E+2 is
hashed as 100), while text NUMERIC preserves it. As a result, the same numeric
value may have different bucket IDs in the two formats. Pass the format used to
send the parameter as decimal_format; asyncpg uses DecimalFormat.BINARY, while
psycopg uses DecimalFormat.TEXT for regular %s placeholders. This behavior
should be revisited when
the Picodata issue is fixed.
type_oid is technically a Postgres OID, but a narrow one. Picodata has several user-facing
SQL types
and the scalar types can be used as table distribution. Picodata rejects table creation
with a non-scalar sharding key column.
DecimalFormat
Bases: str, Enum
pgwire format used to send Decimal parameters.
Source code in picopyn/bucket.py
66 67 68 69 70 | |
calculate_bucket_id(dk_meta, params, bucket_count, *, decimal_format=DecimalFormat.BINARY)
Compute the bucket_id a distribution-key-filtered query would land on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dk_meta
|
Sequence[tuple[int, int]]
|
|
required |
params
|
Sequence[Any]
|
The query's bound parameters, in |
required |
bucket_count
|
int
|
Total number of buckets in the target tier. |
required |
decimal_format
|
DecimalFormat
|
pgwire format used to send |
BINARY
|
Returns:
| Type | Description |
|---|---|
int | None
|
The computed
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in picopyn/bucket.py
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | |