1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5#[non_exhaustive]
6pub enum DataError {
7 UnknownColumn(String),
9 UnsupportedKey(String),
11 UnsupportedColumn(String),
13 LiteralMismatch(String),
16 NotNumeric(String),
19 WindowSpan(String),
22 BucketWidth(String),
26 DuplicateName(String),
29 JoinKey(String),
32 JoinTable,
35 ColumnCount {
37 expected: usize,
39 found: usize,
41 },
42 ColumnMismatch {
44 column: usize,
46 },
47 NullKey {
49 row: usize,
51 },
52 KeyType,
54 TooManyRows,
56 Arrow(String),
58}
59
60impl fmt::Display for DataError {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 Self::UnknownColumn(name) => write!(
64 f,
65 "there is no column named {name:?}: names match exactly, case included \
66 (the table's schema lists them)"
67 ),
68 Self::UnsupportedKey(name) => {
69 write!(f, "key column {name:?} must hold integers or strings")
70 }
71 Self::UnsupportedColumn(name) => {
72 write!(
73 f,
74 "views and groups cannot read column {name:?} of this type: they read \
75 booleans, integers, floats, decimals, text (or dictionaries of text), dates, \
76 times, timestamps and durations"
77 )
78 }
79 Self::LiteralMismatch(name) => {
80 write!(f, "the filter does not fit the type of column {name:?}")
81 }
82 Self::NotNumeric(name) => {
83 write!(
84 f,
85 "column {name:?} is not numeric, so it has no sum or mean: those take \
86 integers, decimals and floats (count takes no column; min and max take any column \
87 views can sort)"
88 )
89 }
90 Self::WindowSpan(name) => {
91 write!(
92 f,
93 "the window's span does not fit the type of column {name:?}: \
94 Window::duration goes with dates, times, timestamps and durations, \
95 Window::span (zero or more) with integers, decimals and floats"
96 )
97 }
98 Self::BucketWidth(name) => {
99 write!(
100 f,
101 "the bucket width does not fit the type of column {name:?}: \
102 group_by_time takes at least one of the column's units for dates, times, \
103 timestamps and durations, group_by_step at least one unit for integers \
104 and decimals, or a finite step above zero for floats"
105 )
106 }
107 Self::DuplicateName(name) => write!(
108 f,
109 "two result columns are named {name:?}: give an aggregate another name with \
110 Aggregate::named, or rename the column on one side of a join"
111 ),
112 Self::JoinKey(name) => write!(
113 f,
114 "column {name:?} cannot name the right table's rows: it must hold the same kind \
115 of value as the right key (signed integers, unsigned integers, or text, not a \
116 dictionary)"
117 ),
118 Self::JoinTable => f.write_str(
119 "this table is not the join's output: make it with LookupJoin::table and give \
120 that table to every call",
121 ),
122 Self::ColumnCount { expected, found } => {
123 write!(f, "the batch has {found} columns, the table {expected}")
124 }
125 Self::ColumnMismatch { column } => {
126 write!(
127 f,
128 "column {column} of the batch has another name or data type than the \
129 table's: every batch must have the table's schema (LiveTable::schema)"
130 )
131 }
132 Self::NullKey { row } => write!(f, "row {row} of the batch has a null key"),
133 Self::KeyType => f.write_str(
134 "the keys are not of the key column's kind: give integers for a key column of \
135 integers, strings for one of strings",
136 ),
137 Self::TooManyRows => f.write_str("more than 2^32 live keys, or rows in one batch"),
138 Self::Arrow(message) => write!(f, "Arrow could not build a batch: {message}"),
139 }
140 }
141}
142
143impl std::error::Error for DataError {}
144
145impl DataError {
146 pub(crate) fn arrow(error: arrow_schema::ArrowError) -> Self {
147 Self::Arrow(error.to_string())
148 }
149}