1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use std::fmt;
/// Why a table or view operation was refused. Nothing changes when one is returned.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum DataError {
/// No column has this name.
UnknownColumn(String),
/// The key column must hold integers or strings.
UnsupportedKey(String),
/// Views and groups cannot read this column's data type (lists, structs, binary, ...).
UnsupportedColumn(String),
/// A filter's value or operation does not fit this column's type (text compared with a
/// number, `contains` on a number).
LiteralMismatch(String),
/// Sums and means need an integer, decimal or float column; this one holds something
/// else (text, booleans, dates, times).
NotNumeric(String),
/// A window's span does not fit its column: a `Duration` goes with dates, times and
/// timestamps, a number (zero or more) with integers, decimals and floats.
WindowSpan(String),
/// A group's bucket width does not fit its column: a `Duration` of at least one of its
/// units goes with dates, times and timestamps, a number of at least one unit with
/// integers and decimals, a finite number above zero with floats.
BucketWidth(String),
/// Two columns of a result would have this name: a group spec's, or a join's (a left
/// column and a right one).
DuplicateName(String),
/// A join's `on` column (named here) cannot hold the right table's keys: it must hold the
/// same kind of value, integers (signed or unsigned, as the key) or text.
JoinKey(String),
/// The table given to a join is not laid out as its output (the join's columns, keyed by
/// the left key): make it with `LookupJoin::table`.
JoinTable,
/// The batch has a different number of columns.
ColumnCount {
/// Columns in the table.
expected: usize,
/// Columns in the batch.
found: usize,
},
/// The batch's column at this index has another name or data type.
ColumnMismatch {
/// Index of the first differing column.
column: usize,
},
/// A row of the batch has no key.
NullKey {
/// The row, within the batch.
row: usize,
},
/// Keys to delete or find are not of the key column's kind (text for a number key).
KeyType,
/// More than 2^32 live keys, or rows in one batch.
TooManyRows,
/// Arrow could not build a batch: compacting a table, or assembling groups.
Arrow(String),
}
impl fmt::Display for DataError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::UnknownColumn(name) => write!(
f,
"there is no column named {name:?}: names match exactly, case included \
(the table's schema lists them)"
),
Self::UnsupportedKey(name) => {
write!(f, "key column {name:?} must hold integers or strings")
}
Self::UnsupportedColumn(name) => {
write!(
f,
"views and groups cannot read column {name:?} of this type: they read \
booleans, integers, floats, decimals, text (or dictionaries of text), dates, \
times, timestamps and durations"
)
}
Self::LiteralMismatch(name) => {
write!(f, "the filter does not fit the type of column {name:?}")
}
Self::NotNumeric(name) => {
write!(
f,
"column {name:?} is not numeric, so it has no sum or mean: those take \
integers, decimals and floats (count takes no column; min and max take any column \
views can sort)"
)
}
Self::WindowSpan(name) => {
write!(
f,
"the window's span does not fit the type of column {name:?}: \
Window::duration goes with dates, times, timestamps and durations, \
Window::span (zero or more) with integers, decimals and floats"
)
}
Self::BucketWidth(name) => {
write!(
f,
"the bucket width does not fit the type of column {name:?}: \
group_by_time takes at least one of the column's units for dates, times, \
timestamps and durations, group_by_step at least one unit for integers \
and decimals, or a finite step above zero for floats"
)
}
Self::DuplicateName(name) => write!(
f,
"two result columns are named {name:?}: give an aggregate another name with \
Aggregate::named, or rename the column on one side of a join"
),
Self::JoinKey(name) => write!(
f,
"column {name:?} cannot name the right table's rows: it must hold the same kind \
of value as the right key (signed integers, unsigned integers, or text, not a \
dictionary)"
),
Self::JoinTable => f.write_str(
"this table is not the join's output: make it with LookupJoin::table and give \
that table to every call",
),
Self::ColumnCount { expected, found } => {
write!(f, "the batch has {found} columns, the table {expected}")
}
Self::ColumnMismatch { column } => {
write!(
f,
"column {column} of the batch has another name or data type than the \
table's: every batch must have the table's schema (LiveTable::schema)"
)
}
Self::NullKey { row } => write!(f, "row {row} of the batch has a null key"),
Self::KeyType => f.write_str(
"the keys are not of the key column's kind: give integers for a key column of \
integers, strings for one of strings",
),
Self::TooManyRows => f.write_str("more than 2^32 live keys, or rows in one batch"),
Self::Arrow(message) => write!(f, "Arrow could not build a batch: {message}"),
}
}
}
impl std::error::Error for DataError {}
impl DataError {
pub(crate) fn arrow(error: arrow_schema::ArrowError) -> Self {
Self::Arrow(error.to_string())
}
}