voltdb_client_rust/
table.rs

1use std::collections::HashMap;
2use std::io::Read;
3
4use bigdecimal::BigDecimal;
5use bigdecimal::num_bigint::BigInt;
6use bytebuffer::ByteBuffer;
7use chrono::{DateTime, TimeZone, Utc};
8
9use crate::encode::{*};
10use crate::response::ResponseStatus::Success;
11use crate::response::VoltResponseInfo;
12
13const MIN_INT8: i8 = -1 << 7;
14
15#[derive(Debug, Clone, PartialEq)]
16pub struct Column {
17    pub header_name: String,
18    pub header_type: i8,
19}
20
21#[derive(Debug)]
22pub struct VoltTable {
23    info: VoltResponseInfo,
24    column_count: i16,
25    info_bytes: ByteBuffer,
26    column_info_bytes: ByteBuffer,
27    columns: Vec<Column>,
28    num_rows: i32,
29    rows: Vec<ByteBuffer>,
30    row_index: i32,
31    cn_to_ci: HashMap<String, i16>,
32    column_offsets: Vec<i32>,
33    header_size: i32,
34    total_size: i32,
35}
36
37impl Value for VoltTable {
38    fn get_write_length(&self) -> i32 {
39        return self.total_size + 5;
40    }
41
42    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
43        bytebuffer.write_i8(TABLE);
44        bytebuffer.write_u32(self.total_size as u32);
45        bytebuffer.write_u32(self.header_size as u32);
46        bytebuffer.write_u8(128);
47        bytebuffer.write_bytes(&*self.column_info_bytes.to_bytes());
48        bytebuffer.write_u32(self.num_rows as u32);
49        self.rows.iter().for_each(|f| {
50            bytebuffer.write_u32(f.len() as u32);
51            bytebuffer.write_bytes(&*f.to_bytes());
52        });
53        println!("{}", bytebuffer.len())
54    }
55
56    fn marshal_in_table(&self, _bytebuffer: &mut ByteBuffer, _column_type: i8) {
57        //
58    }
59
60    fn to_value_string(&self) -> String {
61        return "table".to_owned();
62    }
63
64    fn from_bytes(_bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> where Self: Sized {
65        todo!()
66    }
67}
68
69
70impl VoltTable {
71    /// COLUMN HEADER:
72    /// [int: column header size in bytes (non-inclusive)]
73    /// [byte: table status code]
74    /// [short: num columns]
75    /// [byte: column type] * num columns
76    /// [string: column name] * num columns
77    /// TABLE BODY DATA:
78    /// [int: num tuples]
79    /// [int: row size (non inclusive), blob row data] * num tuples
80    pub fn new_table(types: Vec<i8>, header: Vec<String>) -> Self {
81        let mut columns = Vec::with_capacity(types.len());
82        for (i, tp) in types.iter().enumerate() {
83            columns.push(Column {
84                header_name: header.get(i).unwrap().clone(),
85                header_type: *tp,
86            })
87        }
88        return crate::table::VoltTable::new_voltdb_table(columns);
89    }
90
91    pub fn new_voltdb_table(columns: Vec<Column>) -> Self {
92        let mut column_info_bytes = ByteBuffer::new();
93
94        let column_count = columns.len() as i16;
95        column_info_bytes.write_i16(column_count);
96        columns.iter().for_each(|f| column_info_bytes.write_i8(f.header_type));
97        columns.iter().for_each(|f| column_info_bytes.write_string(f.header_name.as_str()));
98        let header_size = (1 + column_info_bytes.len()) as i32;
99        let total_size = header_size + 8;
100        //
101        return VoltTable {
102            info: Default::default(),
103            column_count,
104            info_bytes: Default::default(),
105            column_info_bytes,
106            columns,
107            num_rows: 0,
108            rows: vec![],
109            row_index: 0,
110            cn_to_ci: Default::default(),
111            column_offsets: vec![],
112            header_size,
113            total_size,
114        };
115    }
116
117    pub fn add_row(&mut self, row: Vec<&dyn Value>) -> Result<i16, VoltError> {
118        let mut bf: ByteBuffer = ByteBuffer::new();
119        self.columns.iter().enumerate().for_each(|(f, v)| {
120            let da = *row.get(f).unwrap();
121            da.marshal_in_table(&mut bf, v.header_type);
122        });
123        let len = bf.len();
124        self.rows.push(bf);
125        self.num_rows = self.num_rows + 1;
126        self.total_size = self.total_size + (len + 4) as i32;
127        return Ok(1);
128    }
129
130
131    pub fn get_column_index(&mut self, column: &str) -> Result<i16, VoltError> {
132        let idx = self.cn_to_ci.get(column.to_uppercase().as_str()).ok_or(VoltError::NoValue(column.to_owned()))?;
133        return Ok(*idx);
134    }
135
136    pub fn map_row<'a, T: From<&'a mut VoltTable>>(&'a mut self) -> T {
137        return T::from(self);
138    }
139    pub fn take<T: Value>(&mut self, column: i16) -> Result<T, VoltError> {
140        let bs = self.get_bytes_by_idx(column)?;
141        let column = self.get_column_by_index(column)?;
142        return T::from_bytes(bs, column);
143    }
144
145    pub fn fetch<T: Value>(&mut self, column: &str) -> Result<T, VoltError> {
146        let idx = self.get_column_index(column)?;
147        let bs = self.get_bytes_by_idx(idx)?;
148        let column = self.get_column_by_index(idx)?;
149        return T::from_bytes(bs, column);
150    }
151
152    pub fn debug_row(&mut self) -> String {
153        let x: Vec<String> = self.columns().into_iter().enumerate().map(|(idx, column)| {
154            return format!("{} {:?}", column.header_name, self.get_value_by_idx_type(idx as i16, column.header_type));
155        }).collect();
156        return x.join(" ");
157    }
158
159
160    pub fn has_error(&mut self) -> Option<VoltError> {
161        if self.info.get_status() == Success {
162            return Option::None;
163        }
164        return Option::Some(VoltError::ExecuteFail(self.info.clone()));
165    }
166
167    pub fn advance_row(&mut self) -> bool {
168        return self.advance_to_row(self.row_index + 1);
169    }
170
171    pub fn columns(&self) -> Vec<Column> {
172        self.columns.clone()
173    }
174
175    pub fn col_length(r: &mut ByteBuffer, offset: i32, col_type: i8) -> Result<i32, VoltError> {
176        match col_type {
177            crate::encode::ARRAY_COLUMN => {
178                return Err(VoltError::InvalidColumnType(col_type));
179            }
180            crate::encode::NULL_COLUMN => {
181                return Ok(0);
182            }
183            crate::encode::TINYINT_COLUMN => {
184                return Ok(1);
185            }
186            //SHORT_COLUMN
187            crate::encode::SHORT_COLUMN => {
188                return Ok(2);
189            }
190
191            crate::encode::INT_COLUMN => {
192                return Ok(4);
193            }
194            crate::encode::LONG_COLUMN => {
195                return Ok(8);
196            }
197            crate::encode::FLOAT_COLUMN => {
198                return Ok(8);
199            }
200            crate::encode::STRING_COLUMN => {
201                r.set_rpos(offset as usize);
202                let str_len = r.read_i32()?;
203                if str_len == -1 { // encoding for null string.
204                    return Ok(4);
205                }
206                return Ok(4 + str_len);
207            }
208            crate::encode::TIMESTAMP_COLUMN => {
209                return Ok(8);
210            }
211            crate::encode::DECIMAL_COLUMN => {
212                return Ok(16);
213            }
214            crate::encode::VAR_BIN_COLUMN => {
215                r.set_rpos(offset as usize);
216                let str_len = r.read_i32()?;
217                if str_len == -1 { // encoding for null string.
218                    return Ok(4);
219                }
220                return Ok(4 + str_len); //   4 + str_len;
221            }
222            _ => Err(VoltError::InvalidColumnType(col_type))
223        }
224    }
225
226    fn calc_offsets(&mut self) -> Result<(), VoltError> {
227        let mut offsets = Vec::with_capacity((self.column_count + 1) as usize);
228        let reader = self.rows.get_mut(self.row_index as usize).ok_or(VoltError::NoValue(self.row_index.to_string()))?;
229        offsets.push(0);
230        let mut offset = 0;
231        for i in 0..self.column_count {
232            let column = self.columns.get(i as usize).ok_or(VoltError::NoValue(i.to_string()))?;
233            let length = crate::table::VoltTable::col_length(reader, offset, column.header_type)?;
234            offset = offset + length;
235            offsets.push(offset);
236        }
237        reader.set_rpos(0);
238        self.column_offsets = offsets;
239        return Ok({});
240    }
241
242    pub fn get_value_by_column(&mut self, column: &str) -> Result<Option<Box<dyn Value>>, VoltError> {
243        let idx = self.get_column_index(column)?;
244        return Ok(self.get_value_by_idx(idx)?);
245    }
246
247    pub(crate) fn get_value_by_idx_column(column: &Column, bs: Vec<u8>) -> Result<Option<Box<dyn Value>>, VoltError> {
248        return match column.header_type {
249            crate::encode::TINYINT_COLUMN => {
250                let res = i8::from_bytes(bs, column)?;
251                match res {
252                    i8::MIN => {
253                        Ok(None)
254                    }
255                    _ => {
256                        Ok(Some(Box::new(res)))
257                    }
258                }
259            }
260            crate::encode::SHORT_COLUMN => {
261                let res = i16::from_bytes(bs, column)?;
262                match res {
263                    i16::MIN => {
264                        Ok(None)
265                    }
266                    _ => {
267                        Ok(Some(Box::new(res)))
268                    }
269                }
270            }
271            crate::encode::INT_COLUMN => {
272                let res = i32::from_bytes(bs, column)?;
273                match res {
274                    i32::MIN => {
275                        Ok(None)
276                    }
277                    _ => {
278                        Ok(Some(Box::new(res)))
279                    }
280                }
281            }
282
283            crate::encode::LONG_COLUMN => {
284                let res = i64::from_bytes(bs, column)?;
285                match res {
286                    i64::MIN => {
287                        Ok(None)
288                    }
289                    _ => {
290                        Ok(Some(Box::new(res)))
291                    }
292                }
293            }
294
295            crate::encode::FLOAT_COLUMN => {
296                if bs == NULL_FLOAT_VALUE {
297                    return Ok(None);
298                }
299                let res = f64::from_bytes(bs, column)?;
300                return Ok(Some(Box::new(res)));
301            }
302
303            crate::encode::STRING_COLUMN => {
304                if bs.len() == 4 {
305                    return Ok(None);
306                }
307                let res = String::from_bytes(bs, column)?;
308                return Ok(Some(Box::new(res)));
309            }
310
311            crate::encode::TIMESTAMP_COLUMN => {
312                if bs == NULL_TIMESTAMP {
313                    return Ok(None);
314                }
315                let res = DateTime::from_bytes(bs, column)?;
316                return Ok(Some(Box::new(res)));
317            }
318            crate::encode::DECIMAL_COLUMN => {
319                if bs == NULL_DECIMAL {
320                    return Ok(None);
321                }
322                let res = DateTime::from_bytes(bs, column)?;
323                return Ok(Some(Box::new(res)));
324            }
325            crate::encode::VAR_BIN_COLUMN => {
326                if bs.len() == 4 {
327                    return Ok(None);
328                }
329                let res = Vec::from_bytes(bs, column)?;
330                return Ok(Some(Box::new(res)));
331            }
332            _ => {
333                let res = i16::from_bytes(bs, column)?;
334                // match res {
335                //     Some(v) => {
336                Ok(Some(Box::new(res)))
337                //     }
338                // }
339            }
340        };
341    }
342
343    pub(crate) fn get_value_by_idx_type(&mut self, column: i16, _tp: i8) -> Result<Option<Box<dyn Value>>, VoltError> {
344        let bs = self.get_bytes_by_idx(column)?;
345        let column = self.get_column_by_index(column)?;
346        return crate::table::VoltTable::get_value_by_idx_column(column, bs);
347    }
348
349
350    pub fn get_value_by_idx(&mut self, column: i16) -> Result<Option<Box<dyn Value>>, VoltError> {
351        let tp = self.get_column_type_by_idx(column)?;
352        return self.get_value_by_idx_type(column, tp);
353    }
354
355    pub fn get_bool_by_column(&mut self, column: &str) -> Result<Option<bool>, VoltError> {
356        let idx = self.get_column_index(column)?;
357        return Ok(self.get_bool_by_idx(idx)?);
358    }
359
360    pub fn get_bool_by_idx(&mut self, column: i16) -> Result<Option<bool>, VoltError> {
361        let bs = self.get_bytes_by_idx(column)?;
362        if bs == NULL_BIT_VALUE {
363            return Ok(Option::None);
364        }
365        if bs[0] == 0 {
366            return Ok(Some(false));
367        }
368        return Ok(Some(true));
369    }
370
371    pub fn get_bytes_op_by_column(&mut self, column: &str) -> Result<Option<Vec<u8>>, VoltError> {
372        let idx = self.get_column_index(column)?;
373        return Ok(self.get_bytes_op_by_idx(idx)?);
374    }
375
376    pub fn get_bytes_op_by_idx(&mut self, column: i16) -> Result<Option<Vec<u8>>, VoltError> {
377        let mut bs = self.get_bytes_by_idx(column)?;
378        if bs == NULL_VARCHAR {
379            return Ok(Option::None);
380        }
381        bs.drain(0..4);
382        return Ok(Option::Some(bs));
383    }
384
385    pub fn get_bytes_by_column(&mut self, column: &str) -> Result<Vec<u8>, VoltError> {
386        let idx = self.get_column_index(column)?;
387        return Ok(self.get_bytes_by_idx(idx)?);
388    }
389
390    pub fn get_decimal_by_column(&mut self, column: &str) -> Result<Option<BigDecimal>, VoltError> {
391        let idx = self.get_column_index(column)?;
392        return Ok(self.get_decimal_by_idx(idx)?);
393    }
394
395    pub fn get_decimal_by_idx(&mut self, column: i16) -> Result<Option<BigDecimal>, VoltError> {
396        let bs = self.get_bytes_by_idx(column)?;
397        if bs == NULL_DECIMAL {
398            return Ok(Option::None);
399        }
400        let int = BigInt::from_signed_bytes_be(&*bs);
401        let decimal = BigDecimal::new(int, 12);
402        return Ok(Some(decimal));
403    }
404
405    pub fn get_string_by_column(&mut self, column: &str) -> Result<Option<String>, VoltError> {
406        let idx = self.get_column_index(column)?;
407        return Ok(self.get_string_by_idx(idx)?);
408    }
409
410    pub fn get_column_by_index(&self, column: i16) -> Result<&Column, VoltError> {
411        let res = self.columns.get(column as usize);
412        return match res {
413            None => {
414                Err(VoltError::NoValue(self.row_index.to_string()))
415            }
416            Some(e) => {
417                Ok(e)
418            }
419        };
420    }
421
422    #[allow(mutable_borrow_reservation_conflict)]
423    pub fn get_string_by_idx(&mut self, column: i16) -> Result<Option<String>, VoltError> {
424        let table_column = self.get_column_by_index(column)?; // will change type and name into one map
425        return match table_column.header_type {
426            STRING_COLUMN => {
427                let bs = self.get_bytes_by_idx(column)?;
428                if bs == NULL_VARCHAR {
429                    return Ok(Option::None);
430                }
431                let mut buffer = ByteBuffer::from_bytes(&bs);
432                Ok(Option::Some(buffer.read_string()?))
433            }
434            _ => {
435                let res = self.get_value_by_idx_type(column, table_column.header_type)?;
436                match res {
437                    Some(v) => {
438                        Ok(Option::Some(v.to_value_string()))
439                    }
440                    None => {
441                        Ok(Option::None)
442                    }
443                }
444            }
445        };
446    }
447
448    pub fn get_time_by_column(&mut self, column: &str) -> Result<Option<DateTime<Utc>>, VoltError> {
449        let idx = self.get_column_index(column)?;
450        return Ok(self.get_time_by_idx(idx)?);
451    }
452
453    pub fn get_time_by_idx(&mut self, column: i16) -> Result<Option<DateTime<Utc>>, VoltError> {
454        let bs = self.get_bytes_by_idx(column)?;
455        if bs == NULL_TIMESTAMP {
456            return Ok(Option::None);
457        }
458        let mut buffer = ByteBuffer::from_bytes(&bs);
459        let time = buffer.read_i64()?;
460        return Ok(Option::Some(Utc.timestamp_millis(time / 1000)));
461    }
462
463
464    pub fn get_bytes_by_idx(&mut self, column_index: i16) -> Result<Vec<u8>, VoltError> {
465        if self.column_offsets.len() == 0 {
466            self.calc_offsets()?;
467        }
468        let buffer = self.rows.get_mut(self.row_index as usize).ok_or(VoltError::NoValue(self.row_index.to_string()))?;
469        let start = self.column_offsets.get(column_index as usize).ok_or(VoltError::NoValue(column_index.to_string()))?;
470        let end = self.column_offsets.get(column_index as usize + 1).ok_or(VoltError::NoValue(column_index.to_string()))?;
471        buffer.set_rpos(*start as usize);
472        let rsize = (*end - *start) as usize;
473        Ok(buffer.read_bytes(rsize)?)
474    }
475
476    pub fn advance_to_row(&mut self, row_index: i32) -> bool {
477        if row_index >= self.num_rows {
478            return false;
479        }
480        self.column_offsets = vec![];
481        self.row_index = row_index;
482        return true;
483    }
484
485    fn get_column_type_by_idx(&self, column_idx: i16) -> Result<i8, VoltError> {
486        let v = self.columns.get(column_idx as usize);
487        if v.is_some() {
488            return Ok(v.unwrap().header_type);
489        }
490        return Err(VoltError::NoValue(column_idx.to_string()));
491    }
492}
493
494
495pub fn new_volt_table(bytebuffer: &mut ByteBuffer, info: VoltResponseInfo) -> Result<VoltTable, VoltError> {
496    if info.get_status() != Success {
497        return Ok(VoltTable {
498            info,
499            column_count: -1,
500            info_bytes: Default::default(),
501            column_info_bytes: Default::default(),
502            columns: vec![],
503            num_rows: -1,
504            rows: vec![],
505            row_index: -1,
506            cn_to_ci: Default::default(),
507            column_offsets: vec![],
508            header_size: 0,
509            total_size: 0,
510        });
511    }
512
513    let column_counts = decode_table_common(bytebuffer)?;
514    let mut column_types: Vec<i8> = Vec::with_capacity(column_counts as usize);
515    let mut column_info_bytes = ByteBuffer::new();
516    for _ in 0..column_counts {
517        let tp = bytebuffer.read_i8()?;
518        column_types.push(tp);
519        column_info_bytes.write_i8(tp);
520    }
521    let mut columns: Vec<Column> = Vec::with_capacity(column_counts as usize);
522    let mut cn_to_ci = HashMap::with_capacity(column_counts as usize);
523    for i in 0..column_counts {
524        let name = bytebuffer.read_string()?;
525        columns.push(Column {
526            header_name: name.clone(),
527            header_type: *(column_types.get(i as usize).unwrap()),
528        });
529        column_info_bytes.write_string(name.as_str());
530        cn_to_ci.insert(name, i);
531    }
532    let row_count = bytebuffer.read_i32()?;
533    let mut rows: Vec<ByteBuffer> = Vec::with_capacity(column_counts as usize);
534    for _ in 0..row_count {
535        let row_len = bytebuffer.read_i32()?;
536        let mut build = vec![0; row_len as usize];
537        bytebuffer.read_exact(&mut build)?;
538        let row = ByteBuffer::from_bytes(&*build);
539        rows.push(row);
540    }
541    return Ok(VoltTable {
542        info,
543        column_count: column_counts,
544        info_bytes: Default::default(),
545        column_info_bytes,
546        columns,
547        num_rows: row_count,
548        rows,
549        row_index: -1,
550        cn_to_ci,
551        column_offsets: vec![],
552        header_size: 0,
553        total_size: 0,
554    });
555}
556
557fn decode_table_common(bytebuffer: &mut ByteBuffer) -> Result<i16, VoltError> {
558    let _ttl_length = bytebuffer.read_i32();
559    let _meta_length = bytebuffer.read_i32();
560    let status_code = bytebuffer.read_i8()?;
561    if status_code != 0 && status_code != MIN_INT8 {
562        // copy from golang , but why ?
563        return Err(VoltError::BadReturnStatusOnTable(status_code));
564    }
565    return Ok(bytebuffer.read_i16()?);
566}
567
568
569#[cfg(test)]
570mod tests {
571    use crate::encode::{DECIMAL_COLUMN, FLOAT_COLUMN, INT_COLUMN, LONG_COLUMN, SHORT_COLUMN, STRING_COLUMN, TIMESTAMP_COLUMN, TINYINT_COLUMN, VAR_BIN_COLUMN};
572    use crate::volt_param;
573
574    use super::*;
575
576    fn template(tps: Vec<&str>, none: &str) {
577        for tp in tps {
578            let shader = r#"
579                pub fn get_${type}_by_column (&mut self, column: &str) -> Result<Option<${type}>, VoltError> {
580                    let idx = self.get_column_index(column)?;
581                    return Ok(self.get_${type}_by_idx>](idx)?);
582                }
583
584                pub fn get_${type}_by_idx (&mut self, column: i16) -> Result<Option<${type}>, VoltError> {
585                    let bs = self.get_bytes_by_idx(column)?;
586                    if bs == ${none} {
587                       return Ok(Option::None);
588                    }
589                    let mut buffer = ByteBuffer::from_bytes(&bs);
590                    let value = buffer.read_${type}()?;
591                    return Ok(Some(value));
592                }
593"#;
594            println!("{}", shader.replace("${type}", tp).replace("${none}", none));
595        }
596    }
597
598    #[test]
599    fn test_encode_table() -> Result<(), VoltError> {
600        let bs = vec! {21, 0, 0, 0, 86, 0, 0, 0, 49, 128, 0, 4, 6, 6, 3, 6, 0, 0, 0, 2, 73, 68, 0, 0, 0, 7, 86, 69, 82, 83, 73, 79, 78, 0, 0, 0, 7, 68, 69, 76, 69, 84, 69, 68, 0, 0, 0, 10, 67, 82, 69, 65, 84, 69, 68, 95, 66, 89, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1};
601        let header = vec!["ID", "VERSION", "DELETED", "CREATED_BY"];
602        let tp = vec![LONG_COLUMN, LONG_COLUMN, TINYINT_COLUMN, LONG_COLUMN];
603        let header: Vec<String> = header.iter().map(|f| f.to_string()).collect::<Vec<String>>();
604        let mut x = VoltTable::new_table(tp, header);
605        let data = volt_param! {1 as i64, 1 as i64, false,  1 as i64 };
606        x.add_row(data)?;
607        let mut bf = ByteBuffer::new();
608        x.marshal(&mut bf);
609        assert_eq!(bs, bf.to_bytes());
610        Ok({})
611    }
612
613    #[test]
614    fn test_table() {
615        let bs = vec! {0 as u8, 1, 128, 0, 0, 0, 3, 0, 1, 0, 0, 0, 133, 0, 0, 0, 66, 128, 0, 9, 3, 4, 5, 6, 8, 22, 9, 25, 11, 0, 0, 0, 2, 84, 49, 0, 0, 0, 2, 84, 50, 0, 0, 0, 2, 84, 51, 0, 0, 0, 2, 84, 52, 0, 0, 0, 2, 84, 53, 0, 0, 0, 2, 84, 54, 0, 0, 0, 2, 84, 55, 0, 0, 0, 2, 84, 56, 0, 0, 0, 2, 84, 57, 0, 0, 0, 1, 0, 0, 0, 55, 128, 128, 0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 255, 239, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0};
616        let mut b = ByteBuffer::from_bytes(&bs);
617        let info = VoltResponseInfo::new(&mut b, 1).unwrap();
618        let mut table = new_volt_table(&mut b, info).unwrap();
619        table.advance_row();
620
621        let header = table.columns();
622        assert_eq!(header.len(), 9);
623        assert_eq!(*header.get(0).unwrap(), Column {
624            header_name: "T1".to_owned(),
625            header_type: TINYINT_COLUMN,
626        });
627        assert_eq!(*header.get(1).unwrap(), Column {
628            header_name: "T2".to_owned(),
629            header_type: SHORT_COLUMN,
630        });
631        assert_eq!(*header.get(2).unwrap(), Column {
632            header_name: "T3".to_owned(),
633            header_type: INT_COLUMN,
634        });
635        assert_eq!(*header.get(3).unwrap(), Column {
636            header_name: "T4".to_owned(),
637            header_type: LONG_COLUMN,
638        });
639        assert_eq!(*header.get(4).unwrap(), Column {
640            header_name: "T5".to_owned(),
641            header_type: FLOAT_COLUMN,
642        });
643        assert_eq!(*header.get(5).unwrap(), Column {
644            header_name: "T6".to_owned(),
645            header_type: DECIMAL_COLUMN,
646        });
647        assert_eq!(*header.get(6).unwrap(), Column {
648            header_name: "T7".to_owned(),
649            header_type: STRING_COLUMN,
650        });
651        assert_eq!(*header.get(7).unwrap(), Column {
652            header_name: "T8".to_owned(),
653            header_type: VAR_BIN_COLUMN,
654        });
655        assert_eq!(*header.get(8).unwrap(), Column {
656            header_name: "T9".to_owned(),
657            header_type: TIMESTAMP_COLUMN,
658        });
659
660
661        let i1 = table.get_bool_by_idx(0).unwrap();
662        let i2 = table.get_i16_by_idx(1).unwrap();
663        let i3 = table.get_i32_by_idx(2).unwrap();
664        let i4 = table.get_i64_by_idx(3).unwrap();
665        let i5 = table.get_f64_by_idx(4).unwrap();
666        let i6 = table.get_decimal_by_idx(5).unwrap();
667        let i7 = table.get_string_by_idx(6).unwrap();
668        let i8 = table.get_bytes_op_by_idx(7).unwrap();
669        let i9 = table.get_time_by_idx(8).unwrap();
670
671        assert_eq!(i1, None);
672        assert_eq!(i2, None);
673        assert_eq!(i3, None);
674        assert_eq!(i4, None);
675        assert_eq!(i5, None);
676        assert_eq!(i6, None);
677        assert_eq!(i7, None);
678        assert_eq!(i8, None);
679        assert_eq!(i9, None);
680        let offsets = vec![0, 1, 3, 7, 15, 23, 39, 43, 47, 55];
681        assert_eq!(offsets, table.column_offsets);
682    }
683
684    #[test]
685    fn test_big_decimal() {
686        template(vec!("i8", "u8"), "NULL_BYTE_VALUE");
687        template(vec!("i16", "u16"), "NULL_SHORT_VALUE");
688        template(vec!("i32", "u32"), "NULL_INT_VALUE");
689        template(vec!("i64", "u64"), "NULL_LONG_VALUE");
690        template(vec!("f32", "f64"), "NULL_FLOAT_VALUE");
691    }
692}
693