ytsaurus-helpers
Derive macros for ytsaurus-client.
A job's rows are already described by a Rust struct. A table schema describes the same thing to the cluster, so writing it out again by hand is a chance to disagree with yourself:
use TableRow;
client.create_table?;
Reach for it through the client, which re-exports the derive:
[]
= { = "0.2", = ["derive"] }
What the types mean
| Rust | column type |
|---|---|
i8 i16 i32 i64 |
int8 … int64 |
u8 u16 u32 u64 |
uint8 … uint64 |
f32 / f64 |
float / double |
bool |
boolean |
String, &str, Cow<str> |
utf8 |
Vec<u8>, &[u8] |
string |
YsonValue |
any |
Option<T> |
T, not required |
Text and bytes do not collapse into one type: a Rust String is UTF-8 by
construction and becomes utf8, while Vec<u8> becomes string, which is what
YTsaurus calls a byte string. That distinction is the same one the codec is
careful about, and it is the difference between a column that rejects a
non-UTF-8 byte and one that stores it.
Anything else is a compile error naming the field. Guessing a column type
from an unknown Rust type is how a schema comes to disagree with the data it
describes, and the cluster enforces the schema on every write. Say what you mean
with #[yt(column_type = "…")] — every type the cluster accepts is available by
name, including timestamp, date, interval, json and uuid, which no
Rust type maps to on its own.
Attributes
On the struct:
#[yt(non_strict)] |
let rows carry columns the schema does not mention |
#[yt(unique_keys)] |
promise no two rows share a key; needs a key column |
#[yt(crate_path = "…")] |
for a renamed ytsaurus-client dependency |
On a field:
#[yt(key)] |
a key column, sorted ascending |
#[yt(name = "…")] |
the column name, when it differs from the field's |
#[yt(column_type = "…")] |
the column type, by its wire name |
#[yt(skip)] |
not a column at all |
What it refuses, and why
Each of these is something a cluster answers with error 314 a round trip later. Catching them at compile time turns a nested error document into a message under the field:
- key columns that are not a prefix —
Key columns must form a prefix of schema. The macro names the field to move rather than silently reordering your struct; unique_keyswith no key column — the promise has nothing to be about;- duplicate column names, after renames;
Option<Option<T>>— a column is present or it is not; there is no second layer for a schema to describe.
Three column types can never be required — any, null and void — because
each already means "there may be nothing here". The derive never marks them so,
whatever the Rust type says.