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)]
22#[allow(dead_code)]
23pub struct VoltTable {
24 info: VoltResponseInfo,
25 column_count: i16,
26 info_bytes: ByteBuffer,
27 column_info_bytes: ByteBuffer,
28 columns: Vec<Column>,
29 num_rows: i32,
30 rows: Vec<ByteBuffer>,
31 row_index: i32,
32 cn_to_ci: HashMap<String, i16>,
33 column_offsets: Vec<i32>,
34 header_size: i32,
35 total_size: i32,
36}
37
38impl VoltTable {
39 pub fn get_row_count(&self) -> i32 {
40 self.num_rows
41 }
42}
43
44impl Value for VoltTable {
45 fn get_write_length(&self) -> i32 {
46 self.total_size + 5
47 }
48
49 fn marshal(&self, bytebuffer: &mut ByteBuffer) {
50 bytebuffer.write_i8(TABLE);
51 bytebuffer.write_u32(self.total_size as u32);
52 bytebuffer.write_u32(self.header_size as u32);
53 bytebuffer.write_u8(128);
54 bytebuffer.write_bytes(self.column_info_bytes.as_bytes());
55 bytebuffer.write_u32(self.num_rows as u32);
56 self.rows.iter().for_each(|f| {
57 bytebuffer.write_u32(f.len() as u32);
58 bytebuffer.write_bytes(f.as_bytes());
59 });
60 }
61
62 fn marshal_in_table(&self, _bytebuffer: &mut ByteBuffer, _column_type: i8) {
63 }
65
66 fn to_value_string(&self) -> String {
67 "table".to_owned()
68 }
69
70 fn from_bytes(_bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError>
71 where
72 Self: Sized,
73 {
74 Err(VoltError::Other(
75 "VoltTable::from_bytes is not supported. Use new_volt_table() to parse tables from response data.".to_string()
76 ))
77 }
78}
79
80impl VoltTable {
81 pub fn new_table(types: Vec<i8>, header: Vec<String>) -> Self {
95 assert_eq!(
96 types.len(),
97 header.len(),
98 "Column types and headers must have the same length"
99 );
100 let columns: Vec<Column> = types
101 .iter()
102 .zip(header.iter())
103 .map(|(tp, name)| Column {
104 header_name: name.clone(),
105 header_type: *tp,
106 })
107 .collect();
108 VoltTable::new_voltdb_table(columns)
109 }
110
111 pub fn new_voltdb_table(columns: Vec<Column>) -> Self {
112 let mut column_info_bytes = ByteBuffer::new();
113
114 let column_count = columns.len() as i16;
115 column_info_bytes.write_i16(column_count);
116 columns
117 .iter()
118 .for_each(|f| column_info_bytes.write_i8(f.header_type));
119 columns
120 .iter()
121 .for_each(|f| column_info_bytes.write_string(f.header_name.as_str()));
122 let header_size = (1 + column_info_bytes.len()) as i32;
123 let total_size = header_size + 8;
124 VoltTable {
126 info: Default::default(),
127 column_count,
128 info_bytes: Default::default(),
129 column_info_bytes,
130 columns,
131 num_rows: 0,
132 rows: vec![],
133 row_index: 0,
134 cn_to_ci: Default::default(),
135 column_offsets: vec![],
136 header_size,
137 total_size,
138 }
139 }
140
141 pub fn add_row(&mut self, row: Vec<&dyn Value>) -> Result<i16, VoltError> {
149 if row.len() < self.columns.len() {
150 return Err(VoltError::Other(format!(
151 "Row has {} values but table has {} columns",
152 row.len(),
153 self.columns.len()
154 )));
155 }
156 let mut bf: ByteBuffer = ByteBuffer::new();
157 for (i, col) in self.columns.iter().enumerate() {
158 let value = row[i]; value.marshal_in_table(&mut bf, col.header_type);
160 }
161 let len = bf.len();
162 self.rows.push(bf);
163 self.num_rows += 1;
164 self.total_size += (len + 4) as i32;
165 Ok(1)
166 }
167
168 pub fn get_column_index(&mut self, column: &str) -> Result<i16, VoltError> {
169 let idx = self
170 .cn_to_ci
171 .get(column.to_uppercase().as_str())
172 .ok_or(VoltError::NoValue(column.to_owned()))?;
173 Ok(*idx)
174 }
175
176 pub fn map_row<'a, T: From<&'a mut VoltTable>>(&'a mut self) -> T {
177 T::from(self)
178 }
179 pub fn take<T: Value>(&mut self, column: i16) -> Result<T, VoltError> {
180 let bs = self.get_bytes_by_idx(column)?;
181 let column = self.get_column_by_index(column)?;
182 T::from_bytes(bs, column)
183 }
184
185 pub fn fetch<T: Value>(&mut self, column: &str) -> Result<T, VoltError> {
186 let idx = self.get_column_index(column)?;
187 let bs = self.get_bytes_by_idx(idx)?;
188 let column = self.get_column_by_index(idx)?;
189 T::from_bytes(bs, column)
190 }
191
192 pub fn debug_row(&mut self) -> String {
193 let x: Vec<String> = self
194 .columns()
195 .into_iter()
196 .enumerate()
197 .map(|(idx, column)| {
198 format!(
199 "{} {:?}",
200 column.header_name,
201 self.get_value_by_idx_type(idx as i16, column.header_type)
202 )
203 })
204 .collect();
205 x.join(" ")
206 }
207
208 pub fn has_error(&mut self) -> Option<VoltError> {
209 if self.info.get_status() == Success {
210 return Option::None;
211 }
212 Option::Some(VoltError::ExecuteFail(self.info.clone()))
213 }
214
215 pub fn advance_row(&mut self) -> bool {
216 self.advance_to_row(self.row_index + 1)
217 }
218
219 pub fn columns(&self) -> Vec<Column> {
220 self.columns.clone()
221 }
222
223 pub fn col_length(r: &mut ByteBuffer, offset: i32, col_type: i8) -> Result<i32, VoltError> {
224 match col_type {
225 crate::encode::ARRAY_COLUMN => Err(VoltError::InvalidColumnType(col_type)),
226 crate::encode::NULL_COLUMN => Ok(0),
227 crate::encode::TINYINT_COLUMN => Ok(1),
228 crate::encode::SHORT_COLUMN => Ok(2),
229 crate::encode::INT_COLUMN => Ok(4),
230 crate::encode::LONG_COLUMN => Ok(8),
231 crate::encode::FLOAT_COLUMN => Ok(8),
232 crate::encode::STRING_COLUMN => {
233 r.set_rpos(offset as usize);
234 let str_len = r.read_i32()?;
235 if str_len == -1 {
236 return Ok(4);
238 }
239 Ok(4 + str_len)
240 }
241 crate::encode::TIMESTAMP_COLUMN => Ok(8),
242 crate::encode::DECIMAL_COLUMN => Ok(16),
243 crate::encode::VAR_BIN_COLUMN => {
244 r.set_rpos(offset as usize);
245 let str_len = r.read_i32()?;
246 if str_len == -1 {
247 return Ok(4);
249 }
250 Ok(4 + str_len)
251 }
252 crate::encode::GEOGRAPHY_POINT_COLUMN => Err(VoltError::Other(
253 "GEOGRAPHY_POINT type is not supported. See: https://github.com/johnnywale/voltdb-client-rust".to_string()
254 )),
255 crate::encode::GEOGRAPHY_COLUMN => Err(VoltError::Other(
256 "GEOGRAPHY type is not supported. See: https://github.com/johnnywale/voltdb-client-rust".to_string()
257 )),
258 _ => Err(VoltError::InvalidColumnType(col_type)),
259 }
260 }
261
262 fn calc_offsets(&mut self) -> Result<(), VoltError> {
263 let mut offsets = Vec::with_capacity((self.column_count + 1) as usize);
264 let reader = self
265 .rows
266 .get_mut(self.row_index as usize)
267 .ok_or(VoltError::NoValue(self.row_index.to_string()))?;
268 offsets.push(0);
269 let mut offset = 0;
270 for i in 0..self.column_count {
271 let column = self
272 .columns
273 .get(i as usize)
274 .ok_or(VoltError::NoValue(i.to_string()))?;
275 let length = crate::table::VoltTable::col_length(reader, offset, column.header_type)?;
276 offset += length;
277 offsets.push(offset);
278 }
279 reader.set_rpos(0);
280 self.column_offsets = offsets;
281 Ok(())
282 }
283
284 pub fn get_value_by_column(
285 &mut self,
286 column: &str,
287 ) -> Result<Option<Box<dyn Value>>, VoltError> {
288 let idx = self.get_column_index(column)?;
289 self.get_value_by_idx(idx)
290 }
291
292 pub(crate) fn get_value_by_idx_column(
293 column: &Column,
294 bs: Vec<u8>,
295 ) -> Result<Option<Box<dyn Value>>, VoltError> {
296 match column.header_type {
297 crate::encode::TINYINT_COLUMN => {
298 let res = i8::from_bytes(bs, column)?;
299 match res {
300 i8::MIN => Ok(None),
301 _ => Ok(Some(Box::new(res))),
302 }
303 }
304 crate::encode::SHORT_COLUMN => {
305 let res = i16::from_bytes(bs, column)?;
306 match res {
307 i16::MIN => Ok(None),
308 _ => Ok(Some(Box::new(res))),
309 }
310 }
311 crate::encode::INT_COLUMN => {
312 let res = i32::from_bytes(bs, column)?;
313 match res {
314 i32::MIN => Ok(None),
315 _ => Ok(Some(Box::new(res))),
316 }
317 }
318
319 crate::encode::LONG_COLUMN => {
320 let res = i64::from_bytes(bs, column)?;
321 match res {
322 i64::MIN => Ok(None),
323 _ => Ok(Some(Box::new(res))),
324 }
325 }
326
327 crate::encode::FLOAT_COLUMN => {
328 if bs == NULL_FLOAT_VALUE {
329 return Ok(None);
330 }
331 let res = f64::from_bytes(bs, column)?;
332 Ok(Some(Box::new(res)))
333 }
334
335 crate::encode::STRING_COLUMN => {
336 if bs.len() == 4 {
337 return Ok(None);
338 }
339 let res = String::from_bytes(bs, column)?;
340 Ok(Some(Box::new(res)))
341 }
342
343 crate::encode::TIMESTAMP_COLUMN => {
344 if bs == NULL_TIMESTAMP {
345 return Ok(None);
346 }
347 let res = DateTime::from_bytes(bs, column)?;
348 Ok(Some(Box::new(res)))
349 }
350 crate::encode::DECIMAL_COLUMN => {
351 if bs == NULL_DECIMAL {
352 return Ok(None);
353 }
354 let res = DateTime::from_bytes(bs, column)?;
355 Ok(Some(Box::new(res)))
356 }
357 crate::encode::VAR_BIN_COLUMN => {
358 if bs.len() == 4 {
359 return Ok(None);
360 }
361 let res = Vec::from_bytes(bs, column)?;
362 Ok(Some(Box::new(res)))
363 }
364 _ => {
365 let res = i16::from_bytes(bs, column)?;
366 Ok(Some(Box::new(res)))
369 }
372 }
373 }
374
375 pub(crate) fn get_value_by_idx_type(
376 &mut self,
377 column: i16,
378 _tp: i8,
379 ) -> Result<Option<Box<dyn Value>>, VoltError> {
380 let bs = self.get_bytes_by_idx(column)?;
381 let column = self.get_column_by_index(column)?;
382 crate::table::VoltTable::get_value_by_idx_column(column, bs)
383 }
384
385 pub fn get_value_by_idx(&mut self, column: i16) -> Result<Option<Box<dyn Value>>, VoltError> {
386 let tp = self.get_column_type_by_idx(column)?;
387 self.get_value_by_idx_type(column, tp)
388 }
389
390 pub fn get_bool_by_column(&mut self, column: &str) -> Result<Option<bool>, VoltError> {
391 let idx = self.get_column_index(column)?;
392 self.get_bool_by_idx(idx)
393 }
394
395 pub fn get_bool_by_idx(&mut self, column: i16) -> Result<Option<bool>, VoltError> {
396 let bs = self.get_bytes_by_idx(column)?;
397 if bs == NULL_BIT_VALUE {
398 return Ok(Option::None);
399 }
400 if bs[0] == 0 {
401 return Ok(Some(false));
402 }
403 Ok(Some(true))
404 }
405
406 pub fn get_bytes_op_by_column(&mut self, column: &str) -> Result<Option<Vec<u8>>, VoltError> {
407 let idx = self.get_column_index(column)?;
408 self.get_bytes_op_by_idx(idx)
409 }
410
411 pub fn get_bytes_op_by_idx(&mut self, column: i16) -> Result<Option<Vec<u8>>, VoltError> {
412 let mut bs = self.get_bytes_by_idx(column)?;
413 if bs == NULL_VARCHAR {
414 return Ok(Option::None);
415 }
416 bs.drain(0..4);
417 Ok(Option::Some(bs))
418 }
419
420 pub fn get_bytes_by_column(&mut self, column: &str) -> Result<Vec<u8>, VoltError> {
421 let idx = self.get_column_index(column)?;
422 self.get_bytes_by_idx(idx)
423 }
424
425 pub fn get_decimal_by_column(&mut self, column: &str) -> Result<Option<BigDecimal>, VoltError> {
426 let idx = self.get_column_index(column)?;
427 self.get_decimal_by_idx(idx)
428 }
429
430 pub fn get_decimal_by_idx(&mut self, column: i16) -> Result<Option<BigDecimal>, VoltError> {
431 let bs = self.get_bytes_by_idx(column)?;
432 if bs == NULL_DECIMAL {
433 return Ok(Option::None);
434 }
435 let int = BigInt::from_signed_bytes_be(&bs);
436 let decimal = BigDecimal::new(int, 12);
437 Ok(Some(decimal))
438 }
439
440 pub fn get_string_by_column(&mut self, column: &str) -> Result<Option<String>, VoltError> {
441 let idx = self.get_column_index(column)?;
442 self.get_string_by_idx(idx)
443 }
444
445 pub fn get_column_by_index(&self, column: i16) -> Result<&Column, VoltError> {
446 let res = self.columns.get(column as usize);
447 match res {
448 None => Err(VoltError::NoValue(self.row_index.to_string())),
449 Some(e) => Ok(e),
450 }
451 }
452
453 pub fn get_string_by_idx(&mut self, column: i16) -> Result<Option<String>, VoltError> {
454 let table_column = self.get_column_by_index(column)?; match table_column.header_type {
456 STRING_COLUMN => {
457 let bs = self.get_bytes_by_idx(column)?;
458 if bs == NULL_VARCHAR {
459 return Ok(Option::None);
460 }
461 let mut buffer = ByteBuffer::from_bytes(&bs);
462 Ok(Option::Some(buffer.read_string()?))
463 }
464 _ => {
465 let res = self.get_value_by_idx_type(column, table_column.header_type)?;
466 match res {
467 Some(v) => Ok(Option::Some(v.to_value_string())),
468 None => Ok(Option::None),
469 }
470 }
471 }
472 }
473
474 pub fn get_time_by_column(&mut self, column: &str) -> Result<Option<DateTime<Utc>>, VoltError> {
475 let idx = self.get_column_index(column)?;
476 self.get_time_by_idx(idx)
477 }
478
479 pub fn get_time_by_idx(&mut self, column: i16) -> Result<Option<DateTime<Utc>>, VoltError> {
480 let bs = self.get_bytes_by_idx(column)?;
481 if bs == NULL_TIMESTAMP {
482 return Ok(Option::None);
483 }
484 let mut buffer = ByteBuffer::from_bytes(&bs);
485 let time = buffer.read_i64()?;
486 let millis = time / 1000;
487 match Utc.timestamp_millis_opt(millis) {
488 chrono::LocalResult::Single(dt) => Ok(Option::Some(dt)),
489 _ => Err(VoltError::Other(format!(
490 "Invalid timestamp value: {}",
491 millis
492 ))),
493 }
494 }
495
496 pub fn get_bytes_by_idx(&mut self, column_index: i16) -> Result<Vec<u8>, VoltError> {
497 if self.column_offsets.is_empty() {
498 self.calc_offsets()?;
499 }
500 let buffer = self
501 .rows
502 .get_mut(self.row_index as usize)
503 .ok_or(VoltError::NoValue(self.row_index.to_string()))?;
504 let start = self
505 .column_offsets
506 .get(column_index as usize)
507 .ok_or(VoltError::NoValue(column_index.to_string()))?;
508 let end = self
509 .column_offsets
510 .get(column_index as usize + 1)
511 .ok_or(VoltError::NoValue(column_index.to_string()))?;
512 buffer.set_rpos(*start as usize);
513 let rsize = (*end - *start) as usize;
514 Ok(buffer.read_bytes(rsize)?)
515 }
516
517 pub fn advance_to_row(&mut self, row_index: i32) -> bool {
518 if row_index >= self.num_rows {
519 return false;
520 }
521 self.column_offsets = vec![];
522 self.row_index = row_index;
523 true
524 }
525
526 fn get_column_type_by_idx(&self, column_idx: i16) -> Result<i8, VoltError> {
527 if let Some(v) = self.columns.get(column_idx as usize) {
528 return Ok(v.header_type);
529 }
530 Err(VoltError::NoValue(column_idx.to_string()))
531 }
532}
533
534pub fn new_volt_table(
535 bytebuffer: &mut ByteBuffer,
536 info: VoltResponseInfo,
537) -> Result<VoltTable, VoltError> {
538 if info.get_status() != Success {
539 return Ok(VoltTable {
540 info,
541 column_count: -1,
542 info_bytes: Default::default(),
543 column_info_bytes: Default::default(),
544 columns: vec![],
545 num_rows: -1,
546 rows: vec![],
547 row_index: -1,
548 cn_to_ci: Default::default(),
549 column_offsets: vec![],
550 header_size: 0,
551 total_size: 0,
552 });
553 }
554
555 let column_counts = decode_table_common(bytebuffer)?;
556 let mut column_types: Vec<i8> = Vec::with_capacity(column_counts as usize);
557 let mut column_info_bytes = ByteBuffer::new();
558 for _ in 0..column_counts {
559 let tp = bytebuffer.read_i8()?;
560 column_types.push(tp);
561 column_info_bytes.write_i8(tp);
562 }
563 let mut columns: Vec<Column> = Vec::with_capacity(column_counts as usize);
564 let mut cn_to_ci = HashMap::with_capacity(column_counts as usize);
565 for i in 0..column_counts {
566 let name = bytebuffer.read_string()?;
567 columns.push(Column {
568 header_name: name.clone(),
569 header_type: *(column_types.get(i as usize).unwrap()),
570 });
571 column_info_bytes.write_string(name.as_str());
572 cn_to_ci.insert(name.to_uppercase(), i);
574 }
575 let row_count = bytebuffer.read_i32()?;
576 let mut rows: Vec<ByteBuffer> = Vec::with_capacity(column_counts as usize);
577 for _ in 0..row_count {
578 let row_len = bytebuffer.read_i32()?;
579 let mut build = vec![0; row_len as usize];
580 bytebuffer.read_exact(&mut build)?;
581 let row = ByteBuffer::from_bytes(&build);
582 rows.push(row);
583 }
584 Ok(VoltTable {
585 info,
586 column_count: column_counts,
587 info_bytes: Default::default(),
588 column_info_bytes,
589 columns,
590 num_rows: row_count,
591 rows,
592 row_index: -1,
593 cn_to_ci,
594 column_offsets: vec![],
595 header_size: 0,
596 total_size: 0,
597 })
598}
599
600fn decode_table_common(bytebuffer: &mut ByteBuffer) -> Result<i16, VoltError> {
601 let _ttl_length = bytebuffer.read_i32();
602 let _meta_length = bytebuffer.read_i32();
603 let status_code = bytebuffer.read_i8()?;
604 if status_code != 0 && status_code != MIN_INT8 {
605 return Err(VoltError::BadReturnStatusOnTable(status_code));
607 }
608 Ok(bytebuffer.read_i16()?)
609}
610
611#[cfg(test)]
612mod tests {
613 use crate::encode::{
614 DECIMAL_COLUMN, FLOAT_COLUMN, INT_COLUMN, LONG_COLUMN, SHORT_COLUMN, STRING_COLUMN,
615 TIMESTAMP_COLUMN, TINYINT_COLUMN, VAR_BIN_COLUMN,
616 };
617 use crate::volt_param;
618
619 use super::*;
620
621 fn template(tps: Vec<&str>, none: &str) {
622 for tp in tps {
623 let shader = r#"
624 pub fn get_${type}_by_column (&mut self, column: &str) -> Result<Option<${type}>, VoltError> {
625 let idx = self.get_column_index(column)?;
626 return Ok(self.get_${type}_by_idx>](idx)?);
627 }
628
629 pub fn get_${type}_by_idx (&mut self, column: i16) -> Result<Option<${type}>, VoltError> {
630 let bs = self.get_bytes_by_idx(column)?;
631 if bs == ${none} {
632 return Ok(Option::None);
633 }
634 let mut buffer = ByteBuffer::from_bytes(&bs);
635 let value = buffer.read_${type}()?;
636 return Ok(Some(value));
637 }
638"#;
639 println!("{}", shader.replace("${type}", tp).replace("${none}", none));
640 }
641 }
642
643 #[test]
644 fn test_encode_table() -> Result<(), VoltError> {
645 let bs = vec![
646 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,
647 86, 69, 82, 83, 73, 79, 78, 0, 0, 0, 7, 68, 69, 76, 69, 84, 69, 68, 0, 0, 0, 10, 67,
648 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,
649 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
650 ];
651 let header = ["ID", "VERSION", "DELETED", "CREATED_BY"];
652 let tp = vec![LONG_COLUMN, LONG_COLUMN, TINYINT_COLUMN, LONG_COLUMN];
653 let header: Vec<String> = header
654 .iter()
655 .map(|f| f.to_string())
656 .collect::<Vec<String>>();
657 let mut x = VoltTable::new_table(tp, header);
658 let data = volt_param! {1_i64, 1_i64, false, 1_i64};
659 x.add_row(data)?;
660 let mut bf = ByteBuffer::new();
661 x.marshal(&mut bf);
662 assert_eq!(bs, bf.into_vec());
663 Ok(())
664 }
665
666 #[test]
667 fn test_table() {
668 let bs = vec![
669 0_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,
670 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,
671 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,
672 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,
673 0, 0, 0, 0, 255, 239, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
674 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0,
675 ];
676 let mut b = ByteBuffer::from_bytes(&bs);
677 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
678 let mut table = new_volt_table(&mut b, info).unwrap();
679 table.advance_row();
680
681 let header = table.columns();
682 assert_eq!(header.len(), 9);
683 assert_eq!(
684 *header.first().unwrap(),
685 Column {
686 header_name: "T1".to_owned(),
687 header_type: TINYINT_COLUMN,
688 }
689 );
690 assert_eq!(
691 *header.get(1).unwrap(),
692 Column {
693 header_name: "T2".to_owned(),
694 header_type: SHORT_COLUMN,
695 }
696 );
697 assert_eq!(
698 *header.get(2).unwrap(),
699 Column {
700 header_name: "T3".to_owned(),
701 header_type: INT_COLUMN,
702 }
703 );
704 assert_eq!(
705 *header.get(3).unwrap(),
706 Column {
707 header_name: "T4".to_owned(),
708 header_type: LONG_COLUMN,
709 }
710 );
711 assert_eq!(
712 *header.get(4).unwrap(),
713 Column {
714 header_name: "T5".to_owned(),
715 header_type: FLOAT_COLUMN,
716 }
717 );
718 assert_eq!(
719 *header.get(5).unwrap(),
720 Column {
721 header_name: "T6".to_owned(),
722 header_type: DECIMAL_COLUMN,
723 }
724 );
725 assert_eq!(
726 *header.get(6).unwrap(),
727 Column {
728 header_name: "T7".to_owned(),
729 header_type: STRING_COLUMN,
730 }
731 );
732 assert_eq!(
733 *header.get(7).unwrap(),
734 Column {
735 header_name: "T8".to_owned(),
736 header_type: VAR_BIN_COLUMN,
737 }
738 );
739 assert_eq!(
740 *header.get(8).unwrap(),
741 Column {
742 header_name: "T9".to_owned(),
743 header_type: TIMESTAMP_COLUMN,
744 }
745 );
746
747 let i1 = table.get_bool_by_idx(0).unwrap();
748 let i2 = table.get_i16_by_idx(1).unwrap();
749 let i3 = table.get_i32_by_idx(2).unwrap();
750 let i4 = table.get_i64_by_idx(3).unwrap();
751 let i5 = table.get_f64_by_idx(4).unwrap();
752 let i6 = table.get_decimal_by_idx(5).unwrap();
753 let i7 = table.get_string_by_idx(6).unwrap();
754 let i8 = table.get_bytes_op_by_idx(7).unwrap();
755 let i9 = table.get_time_by_idx(8).unwrap();
756
757 assert_eq!(i1, None);
758 assert_eq!(i2, None);
759 assert_eq!(i3, None);
760 assert_eq!(i4, None);
761 assert_eq!(i5, None);
762 assert_eq!(i6, None);
763 assert_eq!(i7, None);
764 assert_eq!(i8, None);
765 assert_eq!(i9, None);
766 let offsets = vec![0, 1, 3, 7, 15, 23, 39, 43, 47, 55];
767 assert_eq!(offsets, table.column_offsets);
768 }
769
770 #[test]
771 fn test_big_decimal() {
772 template(vec!["i8", "u8"], "NULL_BYTE_VALUE");
773 template(vec!["i16", "u16"], "NULL_SHORT_VALUE");
774 template(vec!["i32", "u32"], "NULL_INT_VALUE");
775 template(vec!["i64", "u64"], "NULL_LONG_VALUE");
776 template(vec!["f32", "f64"], "NULL_FLOAT_VALUE");
777 }
778
779 fn get_value_test_bytes() -> Vec<u8> {
781 vec![
783 0, 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,
784 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, 63, 1, 0, 100, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 42, 64, 9, 33, 251, 84, 68, 45, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 212, 165, 16, 0, 0, 0, 0, 5, 104, 101, 108, 108, 111, 0, 0, 0, 3, 1, 2, 3, 0, 0, 0, 0, 0, 15, 66, 64, ]
805 }
806
807 #[test]
808 fn test_get_bool_by_column() {
809 let bs = get_value_test_bytes();
810 let mut b = ByteBuffer::from_bytes(&bs);
811 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
812 let mut table = new_volt_table(&mut b, info).unwrap();
813 table.advance_row();
814
815 let result = table.get_bool_by_column("T1").unwrap();
816 assert_eq!(result, Some(true));
817 }
818
819 #[test]
820 fn test_get_string_by_column() {
821 let bs = get_value_test_bytes();
822 let mut b = ByteBuffer::from_bytes(&bs);
823 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
824 let mut table = new_volt_table(&mut b, info).unwrap();
825 table.advance_row();
826
827 let result = table.get_string_by_column("T7").unwrap();
828 assert_eq!(result, Some("hello".to_string()));
829 }
830
831 #[test]
832 fn test_get_string_by_idx_from_int() {
833 let bs = get_value_test_bytes();
834 let mut b = ByteBuffer::from_bytes(&bs);
835 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
836 let mut table = new_volt_table(&mut b, info).unwrap();
837 table.advance_row();
838
839 let result = table.get_string_by_idx(2).unwrap();
841 assert_eq!(result, Some("256".to_string()));
842 }
843
844 #[test]
845 fn test_get_bytes_op_by_column() {
846 let bs = get_value_test_bytes();
847 let mut b = ByteBuffer::from_bytes(&bs);
848 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
849 let mut table = new_volt_table(&mut b, info).unwrap();
850 table.advance_row();
851
852 let result = table.get_bytes_op_by_column("T8").unwrap();
853 assert_eq!(result, Some(vec![1, 2, 3]));
854 }
855
856 #[test]
857 fn test_get_decimal_by_column() {
858 let bs = get_value_test_bytes();
859 let mut b = ByteBuffer::from_bytes(&bs);
860 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
861 let mut table = new_volt_table(&mut b, info).unwrap();
862 table.advance_row();
863
864 let result = table.get_decimal_by_column("T6").unwrap();
865 assert!(result.is_some());
866 }
867
868 #[test]
869 fn test_get_time_by_column() {
870 let bs = get_value_test_bytes();
871 let mut b = ByteBuffer::from_bytes(&bs);
872 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
873 let mut table = new_volt_table(&mut b, info).unwrap();
874 table.advance_row();
875
876 let result = table.get_time_by_column("T9").unwrap();
877 assert!(result.is_some());
878 }
879
880 #[test]
881 fn test_get_bytes_by_column() {
882 let bs = get_value_test_bytes();
883 let mut b = ByteBuffer::from_bytes(&bs);
884 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
885 let mut table = new_volt_table(&mut b, info).unwrap();
886 table.advance_row();
887
888 let result = table.get_bytes_by_column("T1").unwrap();
889 assert_eq!(result, vec![1]); }
891
892 #[test]
893 fn test_get_value_by_idx_tinyint() {
894 let bs = get_value_test_bytes();
895 let mut b = ByteBuffer::from_bytes(&bs);
896 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
897 let mut table = new_volt_table(&mut b, info).unwrap();
898 table.advance_row();
899
900 let result = table.get_value_by_idx(0).unwrap();
901 assert!(result.is_some());
902 }
903
904 #[test]
905 fn test_get_value_by_idx_short() {
906 let bs = get_value_test_bytes();
907 let mut b = ByteBuffer::from_bytes(&bs);
908 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
909 let mut table = new_volt_table(&mut b, info).unwrap();
910 table.advance_row();
911
912 let result = table.get_value_by_idx(1).unwrap();
913 assert!(result.is_some());
914 }
915
916 #[test]
917 fn test_get_value_by_idx_int() {
918 let bs = get_value_test_bytes();
919 let mut b = ByteBuffer::from_bytes(&bs);
920 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
921 let mut table = new_volt_table(&mut b, info).unwrap();
922 table.advance_row();
923
924 let result = table.get_value_by_idx(2).unwrap();
925 assert!(result.is_some());
926 }
927
928 #[test]
929 fn test_get_value_by_idx_long() {
930 let bs = get_value_test_bytes();
931 let mut b = ByteBuffer::from_bytes(&bs);
932 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
933 let mut table = new_volt_table(&mut b, info).unwrap();
934 table.advance_row();
935
936 let result = table.get_value_by_idx(3).unwrap();
937 assert!(result.is_some());
938 }
939
940 #[test]
941 fn test_get_value_by_idx_float() {
942 let bs = get_value_test_bytes();
943 let mut b = ByteBuffer::from_bytes(&bs);
944 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
945 let mut table = new_volt_table(&mut b, info).unwrap();
946 table.advance_row();
947
948 let result = table.get_value_by_idx(4).unwrap();
949 assert!(result.is_some());
950 }
951
952 #[test]
953 fn test_get_value_by_idx_string() {
954 let bs = get_value_test_bytes();
955 let mut b = ByteBuffer::from_bytes(&bs);
956 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
957 let mut table = new_volt_table(&mut b, info).unwrap();
958 table.advance_row();
959
960 let result = table.get_value_by_idx(6).unwrap();
961 assert!(result.is_some());
962 }
963
964 #[test]
965 fn test_get_value_by_idx_timestamp() {
966 let bs = get_value_test_bytes();
967 let mut b = ByteBuffer::from_bytes(&bs);
968 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
969 let mut table = new_volt_table(&mut b, info).unwrap();
970 table.advance_row();
971
972 let result = table.get_value_by_idx(8).unwrap();
973 assert!(result.is_some());
974 }
975
976 #[test]
977 fn test_advance_to_row() {
978 let bs = get_value_test_bytes();
979 let mut b = ByteBuffer::from_bytes(&bs);
980 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
981 let mut table = new_volt_table(&mut b, info).unwrap();
982
983 assert!(table.advance_row()); assert!(!table.advance_row()); assert!(table.advance_to_row(0));
989 assert!(!table.advance_to_row(1)); }
991
992 #[test]
993 fn test_fetch() {
994 let bs = get_value_test_bytes();
995 let mut b = ByteBuffer::from_bytes(&bs);
996 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
997 let mut table = new_volt_table(&mut b, info).unwrap();
998 table.advance_row();
999
1000 let result: i32 = table.fetch("T3").unwrap();
1001 assert_eq!(result, 256);
1002 }
1003
1004 #[test]
1005 fn test_take() {
1006 let bs = get_value_test_bytes();
1007 let mut b = ByteBuffer::from_bytes(&bs);
1008 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
1009 let mut table = new_volt_table(&mut b, info).unwrap();
1010 table.advance_row();
1011
1012 let result: i32 = table.take(2).unwrap();
1013 assert_eq!(result, 256);
1014 }
1015
1016 #[test]
1017 fn test_columns() {
1018 let bs = get_value_test_bytes();
1019 let mut b = ByteBuffer::from_bytes(&bs);
1020 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
1021 let table = new_volt_table(&mut b, info).unwrap();
1022
1023 let columns = table.columns();
1024 assert_eq!(columns.len(), 9);
1025 assert_eq!(columns[0].header_name, "T1");
1026 assert_eq!(columns[0].header_type, TINYINT_COLUMN);
1027 }
1028
1029 #[test]
1030 fn test_columns_count() {
1031 let bs = get_value_test_bytes();
1032 let mut b = ByteBuffer::from_bytes(&bs);
1033 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
1034 let table = new_volt_table(&mut b, info).unwrap();
1035
1036 assert_eq!(table.columns().len(), 9);
1038 }
1039
1040 #[test]
1041 fn test_get_column_by_index() {
1042 let bs = get_value_test_bytes();
1043 let mut b = ByteBuffer::from_bytes(&bs);
1044 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
1045 let table = new_volt_table(&mut b, info).unwrap();
1046
1047 let col = table.get_column_by_index(0).unwrap();
1048 assert_eq!(col.header_name, "T1");
1049 assert_eq!(col.header_type, TINYINT_COLUMN);
1050
1051 let err = table.get_column_by_index(100);
1053 assert!(err.is_err());
1054 }
1055
1056 #[test]
1057 fn test_get_column_index_not_found() {
1058 let bs = get_value_test_bytes();
1059 let mut b = ByteBuffer::from_bytes(&bs);
1060 let info = VoltResponseInfo::new(&mut b, 1).unwrap();
1061 let mut table = new_volt_table(&mut b, info).unwrap();
1062 table.advance_row();
1063
1064 let result = table.get_column_index("NONEXISTENT");
1065 assert!(result.is_err());
1066 }
1067
1068 #[test]
1069 fn test_volt_table_to_value_string() {
1070 let header = vec!["ID".to_string()];
1071 let tp = vec![LONG_COLUMN];
1072 let table = VoltTable::new_table(tp, header);
1073
1074 assert_eq!(table.to_value_string(), "table");
1075 }
1076
1077 #[test]
1078 fn test_volt_table_get_write_length() {
1079 let header = vec!["ID".to_string()];
1080 let tp = vec![LONG_COLUMN];
1081 let table = VoltTable::new_table(tp, header);
1082
1083 assert!(table.get_write_length() > 0);
1088 }
1089
1090 #[test]
1091 fn test_new_voltdb_table() {
1092 let columns = vec![
1093 Column {
1094 header_name: "COL1".to_string(),
1095 header_type: INT_COLUMN,
1096 },
1097 Column {
1098 header_name: "COL2".to_string(),
1099 header_type: STRING_COLUMN,
1100 },
1101 ];
1102 let table = VoltTable::new_voltdb_table(columns);
1103
1104 assert_eq!(table.columns().len(), 2);
1105 }
1106}