1use derive_builder::Builder;
18
19use crate::api::v1::{ColumnDataType, SemanticType};
20
21#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum DataTypeExtension {
24 Decimal128 { precision: u8, scale: i8 },
26}
27
28#[derive(Debug, Clone, Builder)]
30#[builder(setter(into))]
31pub struct TableSchema {
32 name: String,
34 #[builder(default)]
36 columns: Vec<Column>,
37}
38
39impl TableSchema {
40 pub fn builder() -> TableSchemaBuilder {
42 TableSchemaBuilder::default()
43 }
44
45 pub fn name(&self) -> &str {
47 &self.name
48 }
49
50 pub fn columns(&self) -> &[Column] {
52 &self.columns
53 }
54
55 pub fn add_tag<T: Into<String>>(mut self, name: T, data_type: ColumnDataType) -> Self {
57 self.columns.push(Column {
58 name: name.into(),
59 data_type,
60 semantic_type: SemanticType::Tag,
61 data_type_extension: None,
62 });
63 self
64 }
65
66 pub fn add_timestamp<T: Into<String>>(mut self, name: T, data_type: ColumnDataType) -> Self {
68 self.columns.push(Column {
69 name: name.into(),
70 data_type,
71 semantic_type: SemanticType::Timestamp,
72 data_type_extension: None,
73 });
74 self
75 }
76
77 pub fn add_field<T: Into<String>>(mut self, name: T, data_type: ColumnDataType) -> Self {
79 self.columns.push(Column {
80 name: name.into(),
81 data_type,
82 semantic_type: SemanticType::Field,
83 data_type_extension: None,
84 });
85 self
86 }
87
88 pub fn add_decimal128_field<T: Into<String>>(
90 mut self,
91 name: T,
92 precision: u8,
93 scale: i8,
94 ) -> Self {
95 self.columns.push(Column {
96 name: name.into(),
97 data_type: ColumnDataType::Decimal128,
98 semantic_type: SemanticType::Field,
99 data_type_extension: Some(DataTypeExtension::Decimal128 { precision, scale }),
100 });
101 self
102 }
103}
104
105#[derive(Debug, Clone)]
107pub struct Column {
108 pub name: String,
109 pub data_type: ColumnDataType,
110 pub semantic_type: SemanticType,
111 pub data_type_extension: Option<DataTypeExtension>,
113}
114
115#[derive(Debug, Clone, Default)]
117pub struct Row {
118 values: Vec<Value>,
119}
120
121impl Row {
122 pub fn new() -> Self {
124 Self::default()
125 }
126
127 pub fn with_capacity(capacity: usize) -> Self {
129 Self {
130 values: Vec::with_capacity(capacity),
131 }
132 }
133
134 pub fn len(&self) -> usize {
136 self.values.len()
137 }
138
139 pub fn is_empty(&self) -> bool {
141 self.values.is_empty()
142 }
143
144 pub fn from_values(values: Vec<Value>) -> Self {
146 Self { values }
147 }
148
149 pub fn add_value(mut self, value: Value) -> Self {
151 self.values.push(value);
152 self
153 }
154
155 pub fn add_values(mut self, values: Vec<Value>) -> Self {
157 self.values.extend(values);
158 self
159 }
160
161 pub fn add_values_iter(mut self, values: impl IntoIterator<Item = Value>) -> Self {
163 self.values.extend(values);
164 self
165 }
166
167 pub fn get_bool(&self, index: usize) -> Option<bool> {
169 match self.values.get(index)? {
170 Value::Boolean(v) => Some(*v),
171 Value::Null => None,
172 other => handle_type_mismatch(index, "boolean", other),
173 }
174 }
175
176 pub unsafe fn get_bool_unchecked(&self, index: usize) -> Option<bool> {
180 match self.values.get_unchecked(index) {
181 Value::Boolean(v) => Some(*v),
182 Value::Null => None,
183 other => handle_type_mismatch(index, "boolean", other),
184 }
185 }
186
187 pub fn get_i8(&self, index: usize) -> Option<i8> {
189 match self.values.get(index)? {
190 Value::Int8(v) => Some(*v),
191 Value::Null => None,
192 other => handle_type_mismatch(index, "i8", other),
193 }
194 }
195
196 pub unsafe fn get_i8_unchecked(&self, index: usize) -> Option<i8> {
200 match self.values.get_unchecked(index) {
201 Value::Int8(v) => Some(*v),
202 Value::Null => None,
203 other => handle_type_mismatch(index, "i8", other),
204 }
205 }
206
207 pub fn get_i16(&self, index: usize) -> Option<i16> {
209 match self.values.get(index)? {
210 Value::Int16(v) => Some(*v),
211 Value::Null => None,
212 other => handle_type_mismatch(index, "i16", other),
213 }
214 }
215
216 pub unsafe fn get_i16_unchecked(&self, index: usize) -> Option<i16> {
220 match self.values.get_unchecked(index) {
221 Value::Int16(v) => Some(*v),
222 Value::Null => None,
223 other => handle_type_mismatch(index, "i16", other),
224 }
225 }
226
227 pub fn get_i32(&self, index: usize) -> Option<i32> {
229 match self.values.get(index)? {
230 Value::Int32(v) => Some(*v),
231 Value::Null => None,
232 other => handle_type_mismatch(index, "i32", other),
233 }
234 }
235
236 pub unsafe fn get_i32_unchecked(&self, index: usize) -> Option<i32> {
240 match self.values.get_unchecked(index) {
241 Value::Int32(v) => Some(*v),
242 Value::Null => None,
243 other => handle_type_mismatch(index, "i32", other),
244 }
245 }
246
247 pub fn get_i64(&self, index: usize) -> Option<i64> {
249 match self.values.get(index)? {
250 Value::Int64(v) => Some(*v),
251 Value::Null => None,
252 other => handle_type_mismatch(index, "i64", other),
253 }
254 }
255
256 pub unsafe fn get_i64_unchecked(&self, index: usize) -> Option<i64> {
260 match self.values.get_unchecked(index) {
261 Value::Int64(v) => Some(*v),
262 Value::Null => None,
263 other => handle_type_mismatch(index, "i64", other),
264 }
265 }
266
267 pub fn get_u8(&self, index: usize) -> Option<u8> {
269 match self.values.get(index)? {
270 Value::Uint8(v) => Some(*v),
271 Value::Null => None,
272 other => handle_type_mismatch(index, "u8", other),
273 }
274 }
275
276 pub unsafe fn get_u8_unchecked(&self, index: usize) -> Option<u8> {
280 match self.values.get_unchecked(index) {
281 Value::Uint8(v) => Some(*v),
282 Value::Null => None,
283 other => handle_type_mismatch(index, "u8", other),
284 }
285 }
286
287 pub fn get_u16(&self, index: usize) -> Option<u16> {
289 match self.values.get(index)? {
290 Value::Uint16(v) => Some(*v),
291 Value::Null => None,
292 other => handle_type_mismatch(index, "u16", other),
293 }
294 }
295
296 pub unsafe fn get_u16_unchecked(&self, index: usize) -> Option<u16> {
300 match self.values.get_unchecked(index) {
301 Value::Uint16(v) => Some(*v),
302 Value::Null => None,
303 other => handle_type_mismatch(index, "u16", other),
304 }
305 }
306
307 pub fn get_u32(&self, index: usize) -> Option<u32> {
309 match self.values.get(index)? {
310 Value::Uint32(v) => Some(*v),
311 Value::Null => None,
312 other => handle_type_mismatch(index, "u32", other),
313 }
314 }
315
316 pub unsafe fn get_u32_unchecked(&self, index: usize) -> Option<u32> {
320 match self.values.get_unchecked(index) {
321 Value::Uint32(v) => Some(*v),
322 Value::Null => None,
323 other => handle_type_mismatch(index, "u32", other),
324 }
325 }
326
327 pub fn get_u64(&self, index: usize) -> Option<u64> {
329 match self.values.get(index)? {
330 Value::Uint64(v) => Some(*v),
331 Value::Null => None,
332 other => handle_type_mismatch(index, "u64", other),
333 }
334 }
335
336 pub unsafe fn get_u64_unchecked(&self, index: usize) -> Option<u64> {
340 match self.values.get_unchecked(index) {
341 Value::Uint64(v) => Some(*v),
342 Value::Null => None,
343 other => handle_type_mismatch(index, "u64", other),
344 }
345 }
346
347 pub fn get_f32(&self, index: usize) -> Option<f32> {
349 match self.values.get(index)? {
350 Value::Float32(v) => Some(*v),
351 Value::Null => None,
352 other => handle_type_mismatch(index, "f32", other),
353 }
354 }
355
356 pub unsafe fn get_f32_unchecked(&self, index: usize) -> Option<f32> {
360 match self.values.get_unchecked(index) {
361 Value::Float32(v) => Some(*v),
362 Value::Null => None,
363 other => handle_type_mismatch(index, "f32", other),
364 }
365 }
366
367 pub fn get_f64(&self, index: usize) -> Option<f64> {
369 match self.values.get(index)? {
370 Value::Float64(v) => Some(*v),
371 Value::Null => None,
372 other => handle_type_mismatch(index, "f64", other),
373 }
374 }
375
376 pub unsafe fn get_f64_unchecked(&self, index: usize) -> Option<f64> {
380 match self.values.get_unchecked(index) {
381 Value::Float64(v) => Some(*v),
382 Value::Null => None,
383 other => handle_type_mismatch(index, "f64", other),
384 }
385 }
386
387 pub fn get_binary(&self, index: usize) -> Option<Vec<u8>> {
389 match self.values.get(index)? {
390 Value::Binary(v) => Some(v.clone()),
391 Value::String(v) => Some(v.as_bytes().to_vec()), Value::Null => None,
393 other => handle_type_mismatch(index, "binary", other),
394 }
395 }
396
397 pub unsafe fn get_binary_unchecked(&self, index: usize) -> Option<Vec<u8>> {
401 match self.values.get_unchecked(index) {
402 Value::Binary(v) => Some(v.clone()),
403 Value::String(v) => Some(v.as_bytes().to_vec()), Value::Null => None,
405 other => handle_type_mismatch(index, "binary", other),
406 }
407 }
408
409 pub fn take_binary(&mut self, index: usize) -> Option<Vec<u8>> {
411 if index >= self.values.len() {
412 return None;
413 }
414 unsafe { self.take_binary_unchecked(index) }
415 }
416
417 pub unsafe fn take_binary_unchecked(&mut self, index: usize) -> Option<Vec<u8>> {
421 match std::mem::replace(self.values.get_unchecked_mut(index), Value::Null) {
422 Value::Binary(v) => Some(v),
423 Value::String(v) => Some(v.into_bytes()), Value::Null => None,
425 other => handle_type_mismatch(index, "binary", &other),
426 }
427 }
428
429 pub fn get_string(&self, index: usize) -> Option<String> {
431 match self.values.get(index)? {
432 Value::String(v) => Some(v.clone()),
433 Value::Null => None,
434 other => handle_type_mismatch(index, "string", other),
435 }
436 }
437
438 pub unsafe fn get_string_unchecked(&self, index: usize) -> Option<String> {
442 match self.values.get_unchecked(index) {
443 Value::String(v) => Some(v.clone()),
444 Value::Null => None,
445 other => handle_type_mismatch(index, "string", other),
446 }
447 }
448
449 pub fn take_string(&mut self, index: usize) -> Option<String> {
451 if index >= self.values.len() {
452 return None;
453 }
454 unsafe { self.take_string_unchecked(index) }
455 }
456
457 pub unsafe fn take_string_unchecked(&mut self, index: usize) -> Option<String> {
461 match std::mem::replace(self.values.get_unchecked_mut(index), Value::Null) {
462 Value::String(v) => Some(v),
463 Value::Null => None,
464 other => handle_type_mismatch(index, "string", &other),
465 }
466 }
467
468 pub fn get_date(&self, index: usize) -> Option<i32> {
470 match self.values.get(index)? {
471 Value::Date(v) => Some(*v),
472 Value::Null => None,
473 other => handle_type_mismatch(index, "date", other),
474 }
475 }
476
477 pub unsafe fn get_date_unchecked(&self, index: usize) -> Option<i32> {
481 match self.values.get_unchecked(index) {
482 Value::Date(v) => Some(*v),
483 Value::Null => None,
484 other => handle_type_mismatch(index, "date", other),
485 }
486 }
487
488 pub fn get_datetime(&self, index: usize) -> Option<i64> {
490 match self.values.get(index)? {
491 Value::Datetime(v) => Some(*v),
492 Value::Null => None,
493 other => handle_type_mismatch(index, "datetime", other),
494 }
495 }
496
497 pub unsafe fn get_datetime_unchecked(&self, index: usize) -> Option<i64> {
501 match self.values.get_unchecked(index) {
502 Value::Datetime(v) => Some(*v),
503 Value::Null => None,
504 other => handle_type_mismatch(index, "datetime", other),
505 }
506 }
507
508 pub fn get_timestamp(&self, index: usize) -> Option<i64> {
510 match self.values.get(index)? {
511 Value::TimestampSecond(v) => Some(*v),
512 Value::TimestampMillisecond(v) => Some(*v),
513 Value::TimestampMicrosecond(v) => Some(*v),
514 Value::TimestampNanosecond(v) => Some(*v),
515 Value::Null => None,
516 other => handle_type_mismatch(index, "timestamp", other),
517 }
518 }
519
520 pub unsafe fn get_timestamp_unchecked(&self, index: usize) -> Option<i64> {
524 match self.values.get_unchecked(index) {
525 Value::TimestampSecond(v) => Some(*v),
526 Value::TimestampMillisecond(v) => Some(*v),
527 Value::TimestampMicrosecond(v) => Some(*v),
528 Value::TimestampNanosecond(v) => Some(*v),
529 Value::Null => None,
530 other => handle_type_mismatch(index, "timestamp", other),
531 }
532 }
533
534 pub fn get_time32(&self, index: usize) -> Option<i32> {
536 match self.values.get(index)? {
537 Value::TimeSecond(v) => Some(*v),
538 Value::TimeMillisecond(v) => Some(*v),
539 Value::Null => None,
540 other => handle_type_mismatch(index, "time32", other),
541 }
542 }
543
544 pub unsafe fn get_time32_unchecked(&self, index: usize) -> Option<i32> {
548 match self.values.get_unchecked(index) {
549 Value::TimeSecond(v) => Some(*v),
550 Value::TimeMillisecond(v) => Some(*v),
551 Value::Null => None,
552 other => handle_type_mismatch(index, "time32", other),
553 }
554 }
555
556 pub fn get_time64(&self, index: usize) -> Option<i64> {
558 match self.values.get(index)? {
559 Value::TimeMicrosecond(v) => Some(*v),
560 Value::TimeNanosecond(v) => Some(*v),
561 Value::Null => None,
562 other => handle_type_mismatch(index, "time64", other),
563 }
564 }
565
566 pub unsafe fn get_time64_unchecked(&self, index: usize) -> Option<i64> {
570 match self.values.get_unchecked(index) {
571 Value::TimeMicrosecond(v) => Some(*v),
572 Value::TimeNanosecond(v) => Some(*v),
573 Value::Null => None,
574 other => handle_type_mismatch(index, "time64", other),
575 }
576 }
577
578 pub fn get_decimal128(&self, index: usize) -> Option<i128> {
580 match self.values.get(index)? {
581 Value::Decimal128(v) => Some(*v),
582 Value::Null => None,
583 other => handle_type_mismatch(index, "decimal128", other),
584 }
585 }
586
587 pub unsafe fn get_decimal128_unchecked(&self, index: usize) -> Option<i128> {
591 match self.values.get_unchecked(index) {
592 Value::Decimal128(v) => Some(*v),
593 Value::Null => None,
594 other => handle_type_mismatch(index, "decimal128", other),
595 }
596 }
597}
598
599#[inline]
601fn handle_type_mismatch<T>(index: usize, expected: &str, actual: &Value) -> Option<T> {
602 if cfg!(debug_assertions) {
603 panic!("Expected `{expected}` value at index {index}, got {actual:?}")
604 }
605 None
606}
607
608#[derive(Debug, Clone)]
610pub enum Value {
611 Boolean(bool),
613
614 Int8(i8),
616 Int16(i16),
617 Int32(i32),
618 Int64(i64),
619 Uint8(u8),
620 Uint16(u16),
621 Uint32(u32),
622 Uint64(u64),
623
624 Float32(f32),
626 Float64(f64),
627
628 Binary(Vec<u8>),
630 String(String),
631
632 Date(i32), Datetime(i64), TimestampSecond(i64),
638 TimestampMillisecond(i64),
639 TimestampMicrosecond(i64),
640 TimestampNanosecond(i64),
641
642 TimeSecond(i32),
644 TimeMillisecond(i32),
645 TimeMicrosecond(i64),
646 TimeNanosecond(i64),
647
648 Decimal128(i128),
650
651 Json(String),
653
654 Null,
656}
657
658#[cfg(test)]
659mod tests {
660 use super::*;
661
662 #[test]
663 fn test_get_bool_correct_types() {
664 let row = Row::from_values(vec![
665 Value::Boolean(true),
666 Value::Boolean(false),
667 Value::Null,
668 ]);
669
670 assert_eq!(row.get_bool(0), Some(true));
672 assert_eq!(row.get_bool(1), Some(false));
673
674 assert_eq!(row.get_bool(2), None);
676 }
677
678 #[test]
679 fn test_get_bool_unchecked_correct_types() {
680 let row = Row::from_values(vec![
681 Value::Boolean(false),
682 Value::Boolean(true),
683 Value::Null,
684 ]);
685
686 unsafe {
687 assert_eq!(row.get_bool_unchecked(0), Some(false));
689 assert_eq!(row.get_bool_unchecked(1), Some(true));
690
691 assert_eq!(row.get_bool_unchecked(2), None);
693 }
694 }
695
696 #[test]
697 #[should_panic(expected = "Expected `boolean` value at index 0, got Int32(42)")]
698 fn test_get_bool_type_mismatch_debug_assert() {
699 let row = Row::from_values(vec![Value::Int32(42)]);
700
701 let _ = row.get_bool(0);
703 }
704
705 #[test]
706 #[should_panic(expected = "Expected `boolean` value at index 0, got String(\"test\")")]
707 fn test_get_bool_unchecked_type_mismatch_debug_assert() {
708 let row = Row::from_values(vec![Value::String("test".to_string())]);
709
710 unsafe {
711 let _ = row.get_bool_unchecked(0);
713 }
714 }
715}