1use crate::dates;
3use crate::decimal::TPCHDecimal;
4use crate::distribution::Distribution;
5use crate::distribution::Distributions;
6use crate::random::RandomPhoneNumber;
7use crate::random::RowRandomInt;
8use crate::random::{PhoneNumberInstance, RandomBoundedLong, StringSequenceInstance};
9use crate::random::{RandomAlphaNumeric, RandomAlphaNumericInstance};
10use crate::text::TextPool;
11use core::fmt;
12use std::fmt::Display;
13
14use crate::dates::{GenerateUtils, TPCHDate};
15use crate::random::{RandomBoundedInt, RandomString, RandomStringSequence, RandomText};
16
17#[derive(Debug, Clone)]
19pub struct NationGenerator<'a> {
20 distributions: &'a Distributions,
21 text_pool: &'a TextPool,
22}
23
24impl Default for NationGenerator<'_> {
25 fn default() -> Self {
26 Self::new(1.0, 1, 1)
28 }
29}
30
31impl<'a> NationGenerator<'a> {
32 pub fn new(_scale_factor: f64, _part: i32, _part_count: i32) -> NationGenerator<'static> {
42 Self::new_with_distributions_and_text_pool(
44 Distributions::static_default(),
45 TextPool::get_or_init_default(),
46 )
47 }
48
49 pub fn new_with_distributions_and_text_pool<'b>(
51 distributions: &'b Distributions,
52 text_pool: &'b TextPool,
53 ) -> NationGenerator<'b> {
54 NationGenerator {
55 distributions,
56 text_pool,
57 }
58 }
59
60 pub fn iter(&self) -> NationGeneratorIterator<'a> {
62 NationGeneratorIterator::new(self.distributions.nations(), self.text_pool)
63 }
64}
65
66impl<'a> IntoIterator for NationGenerator<'a> {
67 type Item = Nation<'a>;
68 type IntoIter = NationGeneratorIterator<'a>;
69
70 fn into_iter(self) -> Self::IntoIter {
71 self.iter()
72 }
73}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
85pub struct Nation<'a> {
86 pub n_nationkey: i64,
88 pub n_name: &'a str,
90 pub n_regionkey: i64,
92 pub n_comment: &'a str,
94}
95
96impl fmt::Display for Nation<'_> {
97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 write!(
99 f,
100 "{}|{}|{}|{}|",
101 self.n_nationkey, self.n_name, self.n_regionkey, self.n_comment
102 )
103 }
104}
105
106impl<'a> Nation<'a> {
107 pub fn new(n_nationkey: i64, n_name: &'a str, n_regionkey: i64, n_comment: &'a str) -> Self {
109 Nation {
110 n_nationkey,
111 n_name,
112 n_regionkey,
113 n_comment,
114 }
115 }
116}
117
118#[derive(Debug)]
120pub struct NationGeneratorIterator<'a> {
121 nations: &'a Distribution,
122 comment_random: RandomText<'a>,
123 index: usize,
124}
125
126impl<'a> NationGeneratorIterator<'a> {
127 const COMMENT_AVERAGE_LENGTH: i32 = 72;
128
129 fn new(nations: &'a Distribution, text_pool: &'a TextPool) -> Self {
130 NationGeneratorIterator {
131 nations,
132 comment_random: RandomText::new(
133 606179079,
134 text_pool,
135 Self::COMMENT_AVERAGE_LENGTH as f64,
136 ),
137 index: 0,
138 }
139 }
140}
141
142impl<'a> Iterator for NationGeneratorIterator<'a> {
143 type Item = Nation<'a>;
144
145 fn next(&mut self) -> Option<Self::Item> {
146 if self.index >= self.nations.size() {
147 return None;
148 }
149
150 let nation = Nation {
151 n_nationkey: self.index as i64,
153 n_name: self.nations.get_value(self.index),
155 n_regionkey: self.nations.get_weight(self.index) as i64,
157 n_comment: self.comment_random.next_value(),
159 };
160
161 self.comment_random.row_finished();
162 self.index += 1;
163
164 Some(nation)
165 }
166}
167
168#[derive(Debug, Clone, PartialEq, Eq)]
178pub struct Region<'a> {
179 pub r_regionkey: i64,
181 pub r_name: &'a str,
183 pub r_comment: &'a str,
185}
186
187impl fmt::Display for Region<'_> {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189 write!(
190 f,
191 "{}|{}|{}|",
192 self.r_regionkey, self.r_name, self.r_comment
193 )
194 }
195}
196
197impl<'a> Region<'a> {
198 pub fn new(r_regionkey: i64, r_name: &'a str, r_comment: &'a str) -> Self {
200 Region {
201 r_regionkey,
202 r_name,
203 r_comment,
204 }
205 }
206}
207
208#[derive(Debug, Clone)]
210pub struct RegionGenerator<'a> {
211 distributions: &'a Distributions,
212 text_pool: &'a TextPool,
213}
214
215impl Default for RegionGenerator<'_> {
216 fn default() -> Self {
217 Self::new(1.0, 1, 1)
219 }
220}
221
222impl<'a> RegionGenerator<'a> {
223 pub fn new(_scale_factor: f64, _part: i32, _part_count: i32) -> RegionGenerator<'static> {
233 Self::new_with_distributions_and_text_pool(
235 Distributions::static_default(),
236 TextPool::get_or_init_default(),
237 )
238 }
239
240 pub fn new_with_distributions_and_text_pool<'b>(
242 distributions: &'b Distributions,
243 text_pool: &'b TextPool,
244 ) -> RegionGenerator<'b> {
245 RegionGenerator {
246 distributions,
247 text_pool,
248 }
249 }
250
251 pub fn iter(&self) -> RegionGeneratorIterator<'a> {
253 RegionGeneratorIterator::new(self.distributions.regions(), self.text_pool)
254 }
255}
256
257impl<'a> IntoIterator for &'a RegionGenerator<'a> {
258 type Item = Region<'a>;
259 type IntoIter = RegionGeneratorIterator<'a>;
260
261 fn into_iter(self) -> Self::IntoIter {
262 self.iter()
263 }
264}
265
266#[derive(Debug)]
268pub struct RegionGeneratorIterator<'a> {
269 regions: &'a Distribution,
270 comment_random: RandomText<'a>,
271 index: usize,
272}
273
274impl<'a> RegionGeneratorIterator<'a> {
275 const COMMENT_AVERAGE_LENGTH: i32 = 72;
276
277 fn new(regions: &'a Distribution, text_pool: &'a TextPool) -> Self {
278 RegionGeneratorIterator {
279 regions,
280 comment_random: RandomText::new(
281 1500869201,
282 text_pool,
283 Self::COMMENT_AVERAGE_LENGTH as f64,
284 ),
285 index: 0,
286 }
287 }
288}
289
290impl<'a> Iterator for RegionGeneratorIterator<'a> {
291 type Item = Region<'a>;
292
293 fn next(&mut self) -> Option<Self::Item> {
294 if self.index >= self.regions.size() {
295 return None;
296 }
297
298 let region = Region {
299 r_regionkey: self.index as i64,
300 r_name: self.regions.get_value(self.index),
301 r_comment: self.comment_random.next_value(),
302 };
303
304 self.comment_random.row_finished();
305 self.index += 1;
306
307 Some(region)
308 }
309}
310
311#[derive(Debug, Clone, Copy, PartialEq)]
313pub struct PartManufacturerName(i32);
314
315impl PartManufacturerName {
316 pub fn new(value: i32) -> Self {
317 PartManufacturerName(value)
318 }
319}
320
321impl fmt::Display for PartManufacturerName {
322 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
323 write!(f, "Manufacturer#{}", self.0)
324 }
325}
326
327#[derive(Debug, Clone, Copy, PartialEq)]
329pub struct PartBrandName(i32);
330
331impl PartBrandName {
332 pub fn new(value: i32) -> Self {
333 PartBrandName(value)
334 }
335}
336
337impl fmt::Display for PartBrandName {
338 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339 write!(f, "Brand#{}", self.0)
340 }
341}
342
343#[derive(Debug, Clone, PartialEq)]
353pub struct Part<'a> {
354 pub p_partkey: i64,
356 pub p_name: StringSequenceInstance<'a>,
358 pub p_mfgr: PartManufacturerName,
360 pub p_brand: PartBrandName,
362 pub p_type: &'a str,
364 pub p_size: i32,
366 pub p_container: &'a str,
368 pub p_retailprice: TPCHDecimal,
370 pub p_comment: &'a str,
372}
373
374impl fmt::Display for Part<'_> {
375 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
376 write!(
377 f,
378 "{}|{}|{}|{}|{}|{}|{}|{}|{}|",
379 self.p_partkey,
380 self.p_name,
381 self.p_mfgr,
382 self.p_brand,
383 self.p_type,
384 self.p_size,
385 self.p_container,
386 self.p_retailprice,
387 self.p_comment
388 )
389 }
390}
391
392#[derive(Debug, Clone)]
394pub struct PartGenerator<'a> {
395 scale_factor: f64,
396 part: i32,
397 part_count: i32,
398 distributions: &'a Distributions,
399 text_pool: &'a TextPool,
400}
401
402impl<'a> PartGenerator<'a> {
403 const SCALE_BASE: i32 = 200_000;
405
406 const NAME_WORDS: i32 = 5;
408 const MANUFACTURER_MIN: i32 = 1;
409 const MANUFACTURER_MAX: i32 = 5;
410 const BRAND_MIN: i32 = 1;
411 const BRAND_MAX: i32 = 5;
412 const SIZE_MIN: i32 = 1;
413 const SIZE_MAX: i32 = 50;
414 const COMMENT_AVERAGE_LENGTH: i32 = 14;
415
416 pub fn new(scale_factor: f64, part: i32, part_count: i32) -> PartGenerator<'static> {
421 Self::new_with_distributions_and_text_pool(
423 scale_factor,
424 part,
425 part_count,
426 Distributions::static_default(),
427 TextPool::get_or_init_default(),
428 )
429 }
430
431 pub fn new_with_distributions_and_text_pool<'b>(
433 scale_factor: f64,
434 part: i32,
435 part_count: i32,
436 distributions: &'b Distributions,
437 text_pool: &'b TextPool,
438 ) -> PartGenerator<'b> {
439 PartGenerator {
440 scale_factor,
441 part,
442 part_count,
443 distributions,
444 text_pool,
445 }
446 }
447
448 pub fn calculate_row_count(scale_factor: f64, part: i32, part_count: i32) -> i64 {
450 GenerateUtils::calculate_row_count(Self::SCALE_BASE, scale_factor, part, part_count)
451 }
452
453 pub fn iter(&self) -> PartGeneratorIterator<'a> {
455 PartGeneratorIterator::new(
456 self.distributions,
457 self.text_pool,
458 GenerateUtils::calculate_start_index(
459 Self::SCALE_BASE,
460 self.scale_factor,
461 self.part,
462 self.part_count,
463 ),
464 Self::calculate_row_count(self.scale_factor, self.part, self.part_count),
465 )
466 }
467}
468
469impl<'a> IntoIterator for &'a PartGenerator<'a> {
470 type Item = Part<'a>;
471 type IntoIter = PartGeneratorIterator<'a>;
472
473 fn into_iter(self) -> Self::IntoIter {
474 self.iter()
475 }
476}
477
478#[derive(Debug)]
480pub struct PartGeneratorIterator<'a> {
481 name_random: RandomStringSequence<'a>,
482 manufacturer_random: RandomBoundedInt,
483 brand_random: RandomBoundedInt,
484 type_random: RandomString<'a>,
485 size_random: RandomBoundedInt,
486 container_random: RandomString<'a>,
487 comment_random: RandomText<'a>,
488
489 start_index: i64,
490 row_count: i64,
491 index: i64,
492}
493
494impl<'a> PartGeneratorIterator<'a> {
495 fn new(
496 distributions: &'a Distributions,
497 text_pool: &'a TextPool,
498 start_index: i64,
499 row_count: i64,
500 ) -> Self {
501 let mut name_random = RandomStringSequence::new(
502 709314158,
503 PartGenerator::NAME_WORDS,
504 distributions.part_colors(),
505 );
506 let mut manufacturer_random = RandomBoundedInt::new(
507 1,
508 PartGenerator::MANUFACTURER_MIN,
509 PartGenerator::MANUFACTURER_MAX,
510 );
511 let mut brand_random =
512 RandomBoundedInt::new(46831694, PartGenerator::BRAND_MIN, PartGenerator::BRAND_MAX);
513 let mut type_random = RandomString::new(1841581359, distributions.part_types());
514 let mut size_random =
515 RandomBoundedInt::new(1193163244, PartGenerator::SIZE_MIN, PartGenerator::SIZE_MAX);
516 let mut container_random = RandomString::new(727633698, distributions.part_containers());
517 let mut comment_random = RandomText::new(
518 804159733,
519 text_pool,
520 PartGenerator::COMMENT_AVERAGE_LENGTH as f64,
521 );
522
523 name_random.advance_rows(start_index);
525 manufacturer_random.advance_rows(start_index);
526 brand_random.advance_rows(start_index);
527 type_random.advance_rows(start_index);
528 size_random.advance_rows(start_index);
529 container_random.advance_rows(start_index);
530 comment_random.advance_rows(start_index);
531
532 PartGeneratorIterator {
533 name_random,
534 manufacturer_random,
535 brand_random,
536 type_random,
537 size_random,
538 container_random,
539 comment_random,
540 start_index,
541 row_count,
542 index: 0,
543 }
544 }
545
546 fn make_part(&mut self, part_key: i64) -> Part<'a> {
548 let name = self.name_random.next_value();
549
550 let manufacturer = self.manufacturer_random.next_value();
551 let brand = manufacturer * 10 + self.brand_random.next_value();
552
553 Part {
554 p_partkey: part_key,
555 p_name: name,
556 p_mfgr: PartManufacturerName::new(manufacturer),
557 p_brand: PartBrandName::new(brand),
558 p_type: self.type_random.next_value(),
559 p_size: self.size_random.next_value(),
560 p_container: self.container_random.next_value(),
561 p_retailprice: TPCHDecimal(Self::calculate_part_price(part_key)),
562 p_comment: self.comment_random.next_value(),
563 }
564 }
565
566 pub fn calculate_part_price(part_key: i64) -> i64 {
568 let mut price = 90000;
569
570 price += (part_key / 10) % 20001;
572 price += (part_key % 1000) * 100;
573
574 price
575 }
576}
577
578impl<'a> Iterator for PartGeneratorIterator<'a> {
579 type Item = Part<'a>;
580
581 fn next(&mut self) -> Option<Self::Item> {
582 if self.index >= self.row_count {
583 return None;
584 }
585
586 let part = self.make_part(self.start_index + self.index + 1);
587
588 self.name_random.row_finished();
589 self.manufacturer_random.row_finished();
590 self.brand_random.row_finished();
591 self.type_random.row_finished();
592 self.size_random.row_finished();
593 self.container_random.row_finished();
594 self.comment_random.row_finished();
595
596 self.index += 1;
597
598 Some(part)
599 }
600}
601
602#[derive(Debug, Clone, Copy, PartialEq)]
604pub struct SupplierName(i64);
605
606impl SupplierName {
607 pub fn new(value: i64) -> Self {
609 SupplierName(value)
610 }
611}
612
613impl fmt::Display for SupplierName {
614 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
615 write!(f, "Supplier#{:09}", self.0)
616 }
617}
618
619#[derive(Debug, Clone, PartialEq)]
629pub struct Supplier {
630 pub s_suppkey: i64,
632 pub s_name: SupplierName,
634 pub s_address: RandomAlphaNumericInstance,
636 pub s_nationkey: i64,
638 pub s_phone: PhoneNumberInstance,
640 pub s_acctbal: TPCHDecimal,
642 pub s_comment: String,
644}
645
646impl fmt::Display for Supplier {
647 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
648 write!(
649 f,
650 "{}|{}|{}|{}|{}|{}|{}|",
651 self.s_suppkey,
652 self.s_name,
653 self.s_address,
654 self.s_nationkey,
655 self.s_phone,
656 self.s_acctbal,
657 self.s_comment
658 )
659 }
660}
661
662#[derive(Debug, Clone)]
664pub struct SupplierGenerator<'a> {
665 scale_factor: f64,
666 part: i32,
667 part_count: i32,
668 distributions: &'a Distributions,
669 text_pool: &'a TextPool,
670}
671
672impl<'a> SupplierGenerator<'a> {
673 const SCALE_BASE: i32 = 10_000;
675
676 const ACCOUNT_BALANCE_MIN: i32 = -99999;
678 const ACCOUNT_BALANCE_MAX: i32 = 999999;
679 const ADDRESS_AVERAGE_LENGTH: i32 = 25;
680 const COMMENT_AVERAGE_LENGTH: i32 = 63;
681
682 pub const BBB_BASE_TEXT: &'static str = "Customer ";
684 pub const BBB_COMPLAINT_TEXT: &'static str = "Complaints";
685 pub const BBB_RECOMMEND_TEXT: &'static str = "Recommends";
686 pub const BBB_COMMENT_LENGTH: usize =
687 Self::BBB_BASE_TEXT.len() + Self::BBB_COMPLAINT_TEXT.len();
688 pub const BBB_COMMENTS_PER_SCALE_BASE: i32 = 10;
689 pub const BBB_COMPLAINT_PERCENT: i32 = 50;
690
691 pub fn new(scale_factor: f64, part: i32, part_count: i32) -> SupplierGenerator<'static> {
696 Self::new_with_distributions_and_text_pool(
698 scale_factor,
699 part,
700 part_count,
701 Distributions::static_default(),
702 TextPool::get_or_init_default(),
703 )
704 }
705
706 pub fn new_with_distributions_and_text_pool<'b>(
708 scale_factor: f64,
709 part: i32,
710 part_count: i32,
711 distributions: &'b Distributions,
712 text_pool: &'b TextPool,
713 ) -> SupplierGenerator<'b> {
714 SupplierGenerator {
715 scale_factor,
716 part,
717 part_count,
718 distributions,
719 text_pool,
720 }
721 }
722
723 pub fn calculate_row_count(scale_factor: f64, part: i32, part_count: i32) -> i64 {
725 GenerateUtils::calculate_row_count(Self::SCALE_BASE, scale_factor, part, part_count)
726 }
727
728 pub fn iter(&self) -> SupplierGeneratorIterator<'a> {
730 SupplierGeneratorIterator::new(
731 self.distributions,
732 self.text_pool,
733 GenerateUtils::calculate_start_index(
734 Self::SCALE_BASE,
735 self.scale_factor,
736 self.part,
737 self.part_count,
738 ),
739 Self::calculate_row_count(self.scale_factor, self.part, self.part_count),
740 )
741 }
742}
743
744impl<'a> IntoIterator for &'a SupplierGenerator<'a> {
745 type Item = Supplier;
746 type IntoIter = SupplierGeneratorIterator<'a>;
747
748 fn into_iter(self) -> Self::IntoIter {
749 self.iter()
750 }
751}
752
753#[derive(Debug)]
755pub struct SupplierGeneratorIterator<'a> {
756 address_random: RandomAlphaNumeric,
757 nation_key_random: RandomBoundedInt,
758 phone_random: RandomPhoneNumber,
759 account_balance_random: RandomBoundedInt,
760 comment_random: RandomText<'a>,
761 bbb_comment_random: RandomBoundedInt,
762 bbb_junk_random: RowRandomInt,
763 bbb_offset_random: RowRandomInt,
764 bbb_type_random: RandomBoundedInt,
765
766 start_index: i64,
767 row_count: i64,
768 index: i64,
769}
770
771impl<'a> SupplierGeneratorIterator<'a> {
772 fn new(
773 distributions: &Distributions,
774 text_pool: &'a TextPool,
775 start_index: i64,
776 row_count: i64,
777 ) -> Self {
778 let mut address_random =
779 RandomAlphaNumeric::new(706178559, SupplierGenerator::ADDRESS_AVERAGE_LENGTH);
780 let mut nation_key_random =
781 RandomBoundedInt::new(110356601, 0, (distributions.nations().size() - 1) as i32);
782 let mut phone_random = RandomPhoneNumber::new(884434366);
783 let mut account_balance_random = RandomBoundedInt::new(
784 962338209,
785 SupplierGenerator::ACCOUNT_BALANCE_MIN,
786 SupplierGenerator::ACCOUNT_BALANCE_MAX,
787 );
788 let mut comment_random = RandomText::new(
789 1341315363,
790 text_pool,
791 SupplierGenerator::COMMENT_AVERAGE_LENGTH as f64,
792 );
793 let mut bbb_comment_random =
794 RandomBoundedInt::new(202794285, 1, SupplierGenerator::SCALE_BASE);
795 let mut bbb_junk_random = RowRandomInt::new(263032577, 1);
796 let mut bbb_offset_random = RowRandomInt::new(715851524, 1);
797 let mut bbb_type_random = RandomBoundedInt::new(753643799, 0, 100);
798
799 address_random.advance_rows(start_index);
801 nation_key_random.advance_rows(start_index);
802 phone_random.advance_rows(start_index);
803 account_balance_random.advance_rows(start_index);
804 comment_random.advance_rows(start_index);
805 bbb_comment_random.advance_rows(start_index);
806 bbb_junk_random.advance_rows(start_index);
807 bbb_offset_random.advance_rows(start_index);
808 bbb_type_random.advance_rows(start_index);
809
810 SupplierGeneratorIterator {
811 address_random,
812 nation_key_random,
813 phone_random,
814 account_balance_random,
815 comment_random,
816 bbb_comment_random,
817 bbb_junk_random,
818 bbb_offset_random,
819 bbb_type_random,
820 start_index,
821 row_count,
822 index: 0,
823 }
824 }
825
826 fn make_supplier(&mut self, supplier_key: i64) -> Supplier {
828 let mut comment = self.comment_random.next_value().to_string();
829
830 let bbb_comment_random_value = self.bbb_comment_random.next_value();
832 if bbb_comment_random_value <= SupplierGenerator::BBB_COMMENTS_PER_SCALE_BASE {
833 let _buffer = comment.clone();
834
835 let noise = self.bbb_junk_random.next_int(
837 0,
838 (comment.len() - SupplierGenerator::BBB_COMMENT_LENGTH) as i32,
839 ) as usize;
840 let offset = self.bbb_offset_random.next_int(
841 0,
842 (comment.len() - (SupplierGenerator::BBB_COMMENT_LENGTH + noise)) as i32,
843 ) as usize;
844
845 let type_text =
847 if self.bbb_type_random.next_value() < SupplierGenerator::BBB_COMPLAINT_PERCENT {
848 SupplierGenerator::BBB_COMPLAINT_TEXT
849 } else {
850 SupplierGenerator::BBB_RECOMMEND_TEXT
851 };
852
853 let mut modified_comment = String::with_capacity(comment.len());
855 modified_comment.push_str(&comment[..offset]);
856 modified_comment.push_str(SupplierGenerator::BBB_BASE_TEXT);
857 modified_comment.push_str(
858 &comment[offset + SupplierGenerator::BBB_BASE_TEXT.len()
859 ..offset + SupplierGenerator::BBB_BASE_TEXT.len() + noise],
860 );
861 modified_comment.push_str(type_text);
862 modified_comment.push_str(
863 &comment
864 [offset + SupplierGenerator::BBB_BASE_TEXT.len() + noise + type_text.len()..],
865 );
866
867 comment = modified_comment;
868 }
869
870 let nation_key = self.nation_key_random.next_value() as i64;
871
872 Supplier {
873 s_suppkey: supplier_key,
874 s_name: SupplierName::new(supplier_key),
875 s_address: self.address_random.next_value(),
876 s_nationkey: nation_key,
877 s_phone: self.phone_random.next_value(nation_key),
878 s_acctbal: TPCHDecimal(self.account_balance_random.next_value() as i64),
879 s_comment: comment,
880 }
881 }
882}
883
884impl Iterator for SupplierGeneratorIterator<'_> {
885 type Item = Supplier;
886
887 fn next(&mut self) -> Option<Self::Item> {
888 if self.index >= self.row_count {
889 return None;
890 }
891
892 let supplier = self.make_supplier(self.start_index + self.index + 1);
893
894 self.address_random.row_finished();
895 self.nation_key_random.row_finished();
896 self.phone_random.row_finished();
897 self.account_balance_random.row_finished();
898 self.comment_random.row_finished();
899 self.bbb_comment_random.row_finished();
900 self.bbb_junk_random.row_finished();
901 self.bbb_offset_random.row_finished();
902 self.bbb_type_random.row_finished();
903
904 self.index += 1;
905
906 Some(supplier)
907 }
908}
909
910#[derive(Debug, Clone, Copy, PartialEq)]
912pub struct CustomerName(i64);
913
914impl CustomerName {
915 pub fn new(value: i64) -> Self {
917 CustomerName(value)
918 }
919}
920
921impl fmt::Display for CustomerName {
922 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
923 write!(f, "Customer#{:09}", self.0)
924 }
925}
926
927#[derive(Debug, Clone, PartialEq)]
937pub struct Customer<'a> {
938 pub c_custkey: i64,
940 pub c_name: CustomerName,
942 pub c_address: RandomAlphaNumericInstance,
944 pub c_nationkey: i64,
946 pub c_phone: PhoneNumberInstance,
948 pub c_acctbal: TPCHDecimal,
950 pub c_mktsegment: &'a str,
952 pub c_comment: &'a str,
954}
955
956impl fmt::Display for Customer<'_> {
957 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
958 write!(
959 f,
960 "{}|{}|{}|{}|{}|{}|{}|{}|",
961 self.c_custkey,
962 self.c_name,
963 self.c_address,
964 self.c_nationkey,
965 self.c_phone,
966 self.c_acctbal,
967 self.c_mktsegment,
968 self.c_comment
969 )
970 }
971}
972
973#[derive(Debug, Clone)]
975pub struct CustomerGenerator<'a> {
976 scale_factor: f64,
977 part: i32,
978 part_count: i32,
979 distributions: &'a Distributions,
980 text_pool: &'a TextPool,
981}
982
983impl<'a> CustomerGenerator<'a> {
984 const SCALE_BASE: i32 = 150_000;
986
987 const ACCOUNT_BALANCE_MIN: i32 = -99999;
989 const ACCOUNT_BALANCE_MAX: i32 = 999999;
990 const ADDRESS_AVERAGE_LENGTH: i32 = 25;
991 const COMMENT_AVERAGE_LENGTH: i32 = 73;
992
993 pub fn new(scale_factor: f64, part: i32, part_count: i32) -> CustomerGenerator<'static> {
998 Self::new_with_distributions_and_text_pool(
1000 scale_factor,
1001 part,
1002 part_count,
1003 Distributions::static_default(),
1004 TextPool::get_or_init_default(),
1005 )
1006 }
1007
1008 pub fn new_with_distributions_and_text_pool<'b>(
1010 scale_factor: f64,
1011 part: i32,
1012 part_count: i32,
1013 distributions: &'b Distributions,
1014 text_pool: &'b TextPool,
1015 ) -> CustomerGenerator<'b> {
1016 CustomerGenerator {
1017 scale_factor,
1018 part,
1019 part_count,
1020 distributions,
1021 text_pool,
1022 }
1023 }
1024
1025 pub fn calculate_row_count(scale_factor: f64, part: i32, part_count: i32) -> i64 {
1027 GenerateUtils::calculate_row_count(Self::SCALE_BASE, scale_factor, part, part_count)
1028 }
1029
1030 pub fn iter(&self) -> CustomerGeneratorIterator<'a> {
1032 CustomerGeneratorIterator::new(
1033 self.distributions,
1034 self.text_pool,
1035 GenerateUtils::calculate_start_index(
1036 Self::SCALE_BASE,
1037 self.scale_factor,
1038 self.part,
1039 self.part_count,
1040 ),
1041 Self::calculate_row_count(self.scale_factor, self.part, self.part_count),
1042 )
1043 }
1044}
1045
1046impl<'a> IntoIterator for &'a CustomerGenerator<'a> {
1047 type Item = Customer<'a>;
1048 type IntoIter = CustomerGeneratorIterator<'a>;
1049
1050 fn into_iter(self) -> Self::IntoIter {
1051 self.iter()
1052 }
1053}
1054
1055#[derive(Debug)]
1057pub struct CustomerGeneratorIterator<'a> {
1058 address_random: RandomAlphaNumeric,
1059 nation_key_random: RandomBoundedInt,
1060 phone_random: RandomPhoneNumber,
1061 account_balance_random: RandomBoundedInt,
1062 market_segment_random: RandomString<'a>,
1063 comment_random: RandomText<'a>,
1064
1065 start_index: i64,
1066 row_count: i64,
1067 index: i64,
1068}
1069
1070impl<'a> CustomerGeneratorIterator<'a> {
1071 fn new(
1072 distributions: &'a Distributions,
1073 text_pool: &'a TextPool,
1074 start_index: i64,
1075 row_count: i64,
1076 ) -> Self {
1077 let mut address_random =
1078 RandomAlphaNumeric::new(881155353, CustomerGenerator::ADDRESS_AVERAGE_LENGTH);
1079 let mut nation_key_random =
1080 RandomBoundedInt::new(1489529863, 0, (distributions.nations().size() - 1) as i32);
1081 let mut phone_random = RandomPhoneNumber::new(1521138112);
1082 let mut account_balance_random = RandomBoundedInt::new(
1083 298370230,
1084 CustomerGenerator::ACCOUNT_BALANCE_MIN,
1085 CustomerGenerator::ACCOUNT_BALANCE_MAX,
1086 );
1087 let mut market_segment_random =
1088 RandomString::new(1140279430, distributions.market_segments());
1089 let mut comment_random = RandomText::new(
1090 1335826707,
1091 text_pool,
1092 CustomerGenerator::COMMENT_AVERAGE_LENGTH as f64,
1093 );
1094
1095 address_random.advance_rows(start_index);
1097 nation_key_random.advance_rows(start_index);
1098 phone_random.advance_rows(start_index);
1099 account_balance_random.advance_rows(start_index);
1100 market_segment_random.advance_rows(start_index);
1101 comment_random.advance_rows(start_index);
1102
1103 CustomerGeneratorIterator {
1104 address_random,
1105 nation_key_random,
1106 phone_random,
1107 account_balance_random,
1108 market_segment_random,
1109 comment_random,
1110 start_index,
1111 row_count,
1112 index: 0,
1113 }
1114 }
1115
1116 fn make_customer(&mut self, customer_key: i64) -> Customer<'a> {
1118 let nation_key = self.nation_key_random.next_value() as i64;
1119
1120 Customer {
1121 c_custkey: customer_key,
1122 c_name: CustomerName::new(customer_key),
1123 c_address: self.address_random.next_value(),
1124 c_nationkey: nation_key,
1125 c_phone: self.phone_random.next_value(nation_key),
1126 c_acctbal: TPCHDecimal(self.account_balance_random.next_value() as i64),
1127 c_mktsegment: self.market_segment_random.next_value(),
1128 c_comment: self.comment_random.next_value(),
1129 }
1130 }
1131}
1132
1133impl<'a> Iterator for CustomerGeneratorIterator<'a> {
1134 type Item = Customer<'a>;
1135
1136 fn next(&mut self) -> Option<Self::Item> {
1137 if self.index >= self.row_count {
1138 return None;
1139 }
1140
1141 let customer = self.make_customer(self.start_index + self.index + 1);
1142
1143 self.address_random.row_finished();
1144 self.nation_key_random.row_finished();
1145 self.phone_random.row_finished();
1146 self.account_balance_random.row_finished();
1147 self.market_segment_random.row_finished();
1148 self.comment_random.row_finished();
1149
1150 self.index += 1;
1151
1152 Some(customer)
1153 }
1154}
1155
1156#[derive(Debug, Clone, PartialEq)]
1166pub struct PartSupp<'a> {
1167 pub ps_partkey: i64,
1169 pub ps_suppkey: i64,
1171 pub ps_availqty: i32,
1173 pub ps_supplycost: TPCHDecimal,
1175 pub ps_comment: &'a str,
1177}
1178
1179impl fmt::Display for PartSupp<'_> {
1180 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1181 write!(
1182 f,
1183 "{}|{}|{}|{}|{}|",
1184 self.ps_partkey, self.ps_suppkey, self.ps_availqty, self.ps_supplycost, self.ps_comment
1185 )
1186 }
1187}
1188
1189#[derive(Debug, Clone)]
1191pub struct PartSuppGenerator<'a> {
1192 scale_factor: f64,
1193 part: i32,
1194 part_count: i32,
1195 text_pool: &'a TextPool,
1196}
1197
1198impl<'a> PartSuppGenerator<'a> {
1199 const SUPPLIERS_PER_PART: i32 = 4;
1201
1202 const AVAILABLE_QUANTITY_MIN: i32 = 1;
1204 const AVAILABLE_QUANTITY_MAX: i32 = 9999;
1205 const SUPPLY_COST_MIN: i32 = 100;
1206 const SUPPLY_COST_MAX: i32 = 100000;
1207 const COMMENT_AVERAGE_LENGTH: i32 = 124;
1208
1209 pub fn new(scale_factor: f64, part: i32, part_count: i32) -> PartSuppGenerator<'static> {
1214 Self::new_with_text_pool(
1216 scale_factor,
1217 part,
1218 part_count,
1219 TextPool::get_or_init_default(),
1220 )
1221 }
1222
1223 pub fn new_with_text_pool(
1225 scale_factor: f64,
1226 part: i32,
1227 part_count: i32,
1228 text_pool: &TextPool,
1229 ) -> PartSuppGenerator<'_> {
1230 PartSuppGenerator {
1231 scale_factor,
1232 part,
1233 part_count,
1234 text_pool,
1235 }
1236 }
1237
1238 pub fn calculate_row_count(scale_factor: f64, part: i32, part_count: i32) -> i64 {
1240 GenerateUtils::calculate_row_count(
1242 PartGenerator::SCALE_BASE,
1243 scale_factor,
1244 part,
1245 part_count,
1246 )
1247 }
1248
1249 pub fn iter(&self) -> PartSuppGeneratorIterator<'a> {
1251 let scale_base = PartGenerator::SCALE_BASE;
1252
1253 PartSuppGeneratorIterator::new(
1254 self.text_pool,
1255 self.scale_factor,
1256 GenerateUtils::calculate_start_index(
1257 scale_base,
1258 self.scale_factor,
1259 self.part,
1260 self.part_count,
1261 ),
1262 Self::calculate_row_count(self.scale_factor, self.part, self.part_count),
1263 )
1264 }
1265}
1266
1267impl<'a> IntoIterator for &'a PartSuppGenerator<'a> {
1268 type Item = PartSupp<'a>;
1269 type IntoIter = PartSuppGeneratorIterator<'a>;
1270
1271 fn into_iter(self) -> Self::IntoIter {
1272 self.iter()
1273 }
1274}
1275
1276#[derive(Debug)]
1278pub struct PartSuppGeneratorIterator<'a> {
1279 scale_factor: f64,
1280 start_index: i64,
1281 row_count: i64,
1282
1283 available_quantity_random: RandomBoundedInt,
1284 supply_cost_random: RandomBoundedInt,
1285 comment_random: RandomText<'a>,
1286
1287 index: i64,
1288 part_supplier_number: i32,
1289}
1290
1291impl<'a> PartSuppGeneratorIterator<'a> {
1292 fn new(text_pool: &'a TextPool, scale_factor: f64, start_index: i64, row_count: i64) -> Self {
1293 let mut available_quantity_random = RandomBoundedInt::new_with_seeds_per_row(
1294 1671059989,
1295 PartSuppGenerator::AVAILABLE_QUANTITY_MIN,
1296 PartSuppGenerator::AVAILABLE_QUANTITY_MAX,
1297 PartSuppGenerator::SUPPLIERS_PER_PART,
1298 );
1299 let mut supply_cost_random = RandomBoundedInt::new_with_seeds_per_row(
1300 1051288424,
1301 PartSuppGenerator::SUPPLY_COST_MIN,
1302 PartSuppGenerator::SUPPLY_COST_MAX,
1303 PartSuppGenerator::SUPPLIERS_PER_PART,
1304 );
1305 let mut comment_random = RandomText::new_with_expected_row_count(
1306 1961692154,
1307 text_pool,
1308 PartSuppGenerator::COMMENT_AVERAGE_LENGTH as f64,
1309 PartSuppGenerator::SUPPLIERS_PER_PART,
1310 );
1311
1312 available_quantity_random.advance_rows(start_index);
1314 supply_cost_random.advance_rows(start_index);
1315 comment_random.advance_rows(start_index);
1316
1317 PartSuppGeneratorIterator {
1318 scale_factor,
1319 start_index,
1320 row_count,
1321 available_quantity_random,
1322 supply_cost_random,
1323 comment_random,
1324 index: 0,
1325 part_supplier_number: 0,
1326 }
1327 }
1328
1329 fn make_part_supplier(&mut self, part_key: i64) -> PartSupp<'a> {
1331 let supplier_key = Self::select_part_supplier(
1332 part_key,
1333 self.part_supplier_number as i64,
1334 self.scale_factor,
1335 );
1336
1337 let ps_availqty = self.available_quantity_random.next_value();
1338 let ps_supplycost = TPCHDecimal(self.supply_cost_random.next_value() as i64);
1339 let ps_comment = self.comment_random.next_value();
1340
1341 PartSupp {
1342 ps_partkey: part_key,
1343 ps_suppkey: supplier_key,
1344 ps_availqty,
1345 ps_supplycost,
1346 ps_comment,
1347 }
1348 }
1349
1350 pub fn select_part_supplier(part_key: i64, supplier_number: i64, scale_factor: f64) -> i64 {
1352 let supplier_count = (SupplierGenerator::SCALE_BASE as f64 * scale_factor) as i64;
1354
1355 ((part_key
1356 + (supplier_number
1357 * ((supplier_count / PartSuppGenerator::SUPPLIERS_PER_PART as i64)
1358 + ((part_key - 1) / supplier_count))))
1359 % supplier_count)
1360 + 1
1361 }
1362}
1363
1364impl<'a> Iterator for PartSuppGeneratorIterator<'a> {
1365 type Item = PartSupp<'a>;
1366
1367 fn next(&mut self) -> Option<Self::Item> {
1368 if self.index >= self.row_count {
1369 return None;
1370 }
1371
1372 let part_key = self.start_index + self.index + 1;
1373 let part_supplier = self.make_part_supplier(part_key);
1374 self.part_supplier_number += 1;
1375
1376 if self.part_supplier_number >= PartSuppGenerator::SUPPLIERS_PER_PART {
1378 self.available_quantity_random.row_finished();
1379 self.supply_cost_random.row_finished();
1380 self.comment_random.row_finished();
1381
1382 self.index += 1;
1383 self.part_supplier_number = 0;
1384 }
1385
1386 Some(part_supplier)
1387 }
1388}
1389
1390#[derive(Debug, Clone, Copy, PartialEq)]
1392pub struct ClerkName(i32);
1393
1394impl ClerkName {
1395 pub fn new(value: i32) -> Self {
1397 ClerkName(value)
1398 }
1399}
1400
1401impl fmt::Display for ClerkName {
1402 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1403 write!(f, "Clerk#{:09}", self.0)
1404 }
1405}
1406
1407#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd)]
1409pub enum OrderStatus {
1410 Fulfilled,
1412 Open,
1414 Pending,
1416}
1417
1418impl OrderStatus {
1419 pub fn as_str(&self) -> &'static str {
1420 match self {
1421 OrderStatus::Fulfilled => "F",
1422 OrderStatus::Open => "O",
1423 OrderStatus::Pending => "P",
1424 }
1425 }
1426}
1427
1428impl Display for OrderStatus {
1429 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1430 write!(f, "{}", self.as_str())
1431 }
1432}
1433
1434#[derive(Debug, Clone, PartialEq)]
1444pub struct Order<'a> {
1445 pub o_orderkey: i64,
1447 pub o_custkey: i64,
1449 pub o_orderstatus: OrderStatus,
1451 pub o_totalprice: TPCHDecimal,
1453 pub o_orderdate: TPCHDate,
1455 pub o_orderpriority: &'a str,
1457 pub o_clerk: ClerkName,
1459 pub o_shippriority: i32,
1461 pub o_comment: &'a str,
1463}
1464
1465impl fmt::Display for Order<'_> {
1466 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1467 write!(
1468 f,
1469 "{}|{}|{}|{}|{}|{}|{}|{}|{}|",
1470 self.o_orderkey,
1471 self.o_custkey,
1472 self.o_orderstatus,
1473 self.o_totalprice,
1474 self.o_orderdate,
1475 self.o_orderpriority,
1476 self.o_clerk,
1477 self.o_shippriority,
1478 self.o_comment
1479 )
1480 }
1481}
1482
1483#[derive(Debug, Clone)]
1485pub struct OrderGenerator<'a> {
1486 scale_factor: f64,
1487 part: i32,
1488 part_count: i32,
1489 distributions: &'a Distributions,
1490 text_pool: &'a TextPool,
1491}
1492
1493impl<'a> OrderGenerator<'a> {
1494 pub const SCALE_BASE: i32 = 1_500_000;
1496
1497 const CUSTOMER_MORTALITY: i32 = 3; const ORDER_DATE_MIN: i32 = dates::MIN_GENERATE_DATE;
1500 const ORDER_DATE_MAX: i32 =
1501 Self::ORDER_DATE_MIN + (dates::TOTAL_DATE_RANGE - LineItemGenerator::ITEM_SHIP_DAYS - 1);
1502 const CLERK_SCALE_BASE: i32 = 1000;
1503
1504 const LINE_COUNT_MIN: i32 = 1;
1505 pub const LINE_COUNT_MAX: i32 = 7;
1506
1507 const COMMENT_AVERAGE_LENGTH: i32 = 49;
1508
1509 const ORDER_KEY_SPARSE_BITS: i32 = 2;
1510 const ORDER_KEY_SPARSE_KEEP: i32 = 3;
1511 pub fn new(scale_factor: f64, part: i32, part_count: i32) -> OrderGenerator<'static> {
1516 Self::new_with_distributions_and_text_pool(
1518 scale_factor,
1519 part,
1520 part_count,
1521 Distributions::static_default(),
1522 TextPool::get_or_init_default(),
1523 )
1524 }
1525
1526 pub fn new_with_distributions_and_text_pool<'b>(
1528 scale_factor: f64,
1529 part: i32,
1530 part_count: i32,
1531 distributions: &'b Distributions,
1532 text_pool: &'b TextPool,
1533 ) -> OrderGenerator<'b> {
1534 OrderGenerator {
1535 scale_factor,
1536 part,
1537 part_count,
1538 distributions,
1539 text_pool,
1540 }
1541 }
1542
1543 pub fn calculate_row_count(scale_factor: f64, part: i32, part_count: i32) -> i64 {
1545 GenerateUtils::calculate_row_count(Self::SCALE_BASE, scale_factor, part, part_count)
1546 }
1547
1548 pub fn iter(&self) -> OrderGeneratorIterator<'a> {
1550 OrderGeneratorIterator::new(
1551 self.distributions,
1552 self.text_pool,
1553 self.scale_factor,
1554 GenerateUtils::calculate_start_index(
1555 Self::SCALE_BASE,
1556 self.scale_factor,
1557 self.part,
1558 self.part_count,
1559 ),
1560 Self::calculate_row_count(self.scale_factor, self.part, self.part_count),
1561 )
1562 }
1563
1564 pub fn create_order_date_random() -> RandomBoundedInt {
1566 RandomBoundedInt::new(1066728069, Self::ORDER_DATE_MIN, Self::ORDER_DATE_MAX)
1567 }
1568
1569 pub fn create_line_count_random() -> RandomBoundedInt {
1571 RandomBoundedInt::new(1434868289, Self::LINE_COUNT_MIN, Self::LINE_COUNT_MAX)
1572 }
1573
1574 pub fn make_order_key(order_index: i64) -> i64 {
1576 let low_bits = order_index & ((1 << Self::ORDER_KEY_SPARSE_KEEP) - 1);
1577
1578 let mut ok = order_index;
1579 ok >>= Self::ORDER_KEY_SPARSE_KEEP;
1580 ok <<= Self::ORDER_KEY_SPARSE_BITS;
1581 ok <<= Self::ORDER_KEY_SPARSE_KEEP;
1582 ok += low_bits;
1583
1584 ok
1585 }
1586}
1587
1588impl<'a> IntoIterator for &'a OrderGenerator<'a> {
1589 type Item = Order<'a>;
1590 type IntoIter = OrderGeneratorIterator<'a>;
1591
1592 fn into_iter(self) -> Self::IntoIter {
1593 self.iter()
1594 }
1595}
1596
1597#[derive(Debug)]
1599pub struct OrderGeneratorIterator<'a> {
1600 order_date_random: RandomBoundedInt,
1601 line_count_random: RandomBoundedInt,
1602 customer_key_random: RandomBoundedLong,
1603 order_priority_random: RandomString<'a>,
1604 clerk_random: RandomBoundedInt,
1605 comment_random: RandomText<'a>,
1606
1607 line_quantity_random: RandomBoundedInt,
1609 line_discount_random: RandomBoundedInt,
1610 line_tax_random: RandomBoundedInt,
1611 line_part_key_random: RandomBoundedLong,
1612 line_ship_date_random: RandomBoundedInt,
1613
1614 start_index: i64,
1615 row_count: i64,
1616 max_customer_key: i64,
1617
1618 index: i64,
1619}
1620impl<'a> OrderGeneratorIterator<'a> {
1621 fn new(
1622 distributions: &'a Distributions,
1623 text_pool: &'a TextPool,
1624 scale_factor: f64,
1625 start_index: i64,
1626 row_count: i64,
1627 ) -> Self {
1628 let mut order_date_random = OrderGenerator::create_order_date_random();
1629 let mut line_count_random = OrderGenerator::create_line_count_random();
1630
1631 let max_customer_key = (CustomerGenerator::SCALE_BASE as f64 * scale_factor) as i64;
1632
1633 let mut customer_key_random =
1634 RandomBoundedLong::new(851767375, scale_factor >= 30000.0, 1, max_customer_key);
1635
1636 let mut order_priority_random =
1637 RandomString::new(591449447, distributions.order_priority());
1638
1639 let max_clerk = (scale_factor * OrderGenerator::CLERK_SCALE_BASE as f64)
1640 .max(OrderGenerator::CLERK_SCALE_BASE as f64) as i32;
1641 let mut clerk_random = RandomBoundedInt::new(1171034773, 1, max_clerk);
1642
1643 let mut comment_random = RandomText::new(
1644 276090261,
1645 text_pool,
1646 OrderGenerator::COMMENT_AVERAGE_LENGTH as f64,
1647 );
1648
1649 let mut line_quantity_random = LineItemGenerator::create_quantity_random();
1651 let mut line_discount_random = LineItemGenerator::create_discount_random();
1652 let mut line_tax_random = LineItemGenerator::create_tax_random();
1653 let mut line_part_key_random = LineItemGenerator::create_part_key_random(scale_factor);
1654 let mut line_ship_date_random = LineItemGenerator::create_ship_date_random();
1655
1656 order_date_random.advance_rows(start_index);
1658 line_count_random.advance_rows(start_index);
1659 customer_key_random.advance_rows(start_index);
1660 order_priority_random.advance_rows(start_index);
1661 clerk_random.advance_rows(start_index);
1662 comment_random.advance_rows(start_index);
1663
1664 line_quantity_random.advance_rows(start_index);
1665 line_discount_random.advance_rows(start_index);
1666 line_tax_random.advance_rows(start_index);
1667 line_part_key_random.advance_rows(start_index);
1668 line_ship_date_random.advance_rows(start_index);
1669
1670 OrderGeneratorIterator {
1671 order_date_random,
1672 line_count_random,
1673 customer_key_random,
1674 order_priority_random,
1675 clerk_random,
1676 comment_random,
1677 line_quantity_random,
1678 line_discount_random,
1679 line_tax_random,
1680 line_part_key_random,
1681 line_ship_date_random,
1682 start_index,
1683 row_count,
1684 max_customer_key,
1685 index: 0,
1686 }
1687 }
1688
1689 fn make_order(&mut self, index: i64) -> Order<'a> {
1691 let order_key = OrderGenerator::make_order_key(index);
1692
1693 let order_date = self.order_date_random.next_value();
1694
1695 let mut customer_key = self.customer_key_random.next_value();
1697 let mut delta = 1;
1698 while customer_key % OrderGenerator::CUSTOMER_MORTALITY as i64 == 0 {
1699 customer_key += delta;
1700 customer_key = customer_key.min(self.max_customer_key);
1701 delta *= -1;
1702 }
1703
1704 let mut total_price = 0;
1705 let mut shipped_count = 0;
1706
1707 let line_count = self.line_count_random.next_value();
1708 for _ in 0..line_count {
1709 let quantity = self.line_quantity_random.next_value();
1710 let discount = self.line_discount_random.next_value();
1711 let tax = self.line_tax_random.next_value();
1712
1713 let part_key = self.line_part_key_random.next_value();
1714
1715 let part_price = PartGeneratorIterator::calculate_part_price(part_key);
1716 let extended_price = part_price * quantity as i64;
1717 let discounted_price = extended_price * (100 - discount as i64);
1718 total_price += ((discounted_price / 100) * (100 + tax as i64)) / 100;
1719
1720 let ship_date = self.line_ship_date_random.next_value() + order_date;
1721 if TPCHDate::is_in_past(ship_date) {
1722 shipped_count += 1;
1723 }
1724 }
1725
1726 let order_status = if shipped_count == line_count {
1727 OrderStatus::Fulfilled
1728 } else if shipped_count > 0 {
1729 OrderStatus::Pending
1730 } else {
1731 OrderStatus::Open
1732 };
1733
1734 let clerk_id = self.clerk_random.next_value();
1735 let clerk_name = ClerkName::new(clerk_id);
1736
1737 Order {
1738 o_orderkey: order_key,
1739 o_custkey: customer_key,
1740 o_orderstatus: order_status,
1741 o_totalprice: TPCHDecimal(total_price),
1742 o_orderdate: TPCHDate::new(order_date),
1743 o_orderpriority: self.order_priority_random.next_value(),
1744 o_clerk: clerk_name,
1745 o_shippriority: 0, o_comment: self.comment_random.next_value(),
1747 }
1748 }
1749}
1750
1751impl<'a> Iterator for OrderGeneratorIterator<'a> {
1752 type Item = Order<'a>;
1753
1754 fn next(&mut self) -> Option<Self::Item> {
1755 if self.index >= self.row_count {
1756 return None;
1757 }
1758
1759 let order = self.make_order(self.start_index + self.index + 1);
1760
1761 self.order_date_random.row_finished();
1762 self.line_count_random.row_finished();
1763 self.customer_key_random.row_finished();
1764 self.order_priority_random.row_finished();
1765 self.clerk_random.row_finished();
1766 self.comment_random.row_finished();
1767
1768 self.line_quantity_random.row_finished();
1769 self.line_discount_random.row_finished();
1770 self.line_tax_random.row_finished();
1771 self.line_part_key_random.row_finished();
1772 self.line_ship_date_random.row_finished();
1773
1774 self.index += 1;
1775
1776 Some(order)
1777 }
1778}
1779
1780#[derive(Debug, Clone, PartialEq)]
1791pub struct LineItem<'a> {
1792 pub l_orderkey: i64,
1794 pub l_partkey: i64,
1796 pub l_suppkey: i64,
1798 pub l_linenumber: i32,
1800 pub l_quantity: i64,
1803 pub l_extendedprice: TPCHDecimal,
1805 pub l_discount: TPCHDecimal,
1807 pub l_tax: TPCHDecimal,
1809 pub l_returnflag: &'a str,
1811 pub l_linestatus: &'static str,
1813 pub l_shipdate: TPCHDate,
1815 pub l_commitdate: TPCHDate,
1817 pub l_receiptdate: TPCHDate,
1819 pub l_shipinstruct: &'a str,
1821 pub l_shipmode: &'a str,
1823 pub l_comment: &'a str,
1825}
1826
1827impl fmt::Display for LineItem<'_> {
1828 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1829 write!(
1830 f,
1831 "{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|",
1832 self.l_orderkey,
1833 self.l_partkey,
1834 self.l_suppkey,
1835 self.l_linenumber,
1836 self.l_quantity,
1837 self.l_extendedprice,
1838 self.l_discount,
1839 self.l_tax,
1840 self.l_returnflag,
1841 self.l_linestatus,
1842 self.l_shipdate,
1843 self.l_commitdate,
1844 self.l_receiptdate,
1845 self.l_shipinstruct,
1846 self.l_shipmode,
1847 self.l_comment
1848 )
1849 }
1850}
1851
1852#[derive(Debug, Clone)]
1854pub struct LineItemGenerator<'a> {
1855 scale_factor: f64,
1856 part: i32,
1857 part_count: i32,
1858 distributions: &'a Distributions,
1859 text_pool: &'a TextPool,
1860}
1861
1862impl<'a> LineItemGenerator<'a> {
1863 const QUANTITY_MIN: i32 = 1;
1865 const QUANTITY_MAX: i32 = 50;
1866 const TAX_MIN: TPCHDecimal = TPCHDecimal(0); const TAX_MAX: TPCHDecimal = TPCHDecimal(8); const DISCOUNT_MIN: TPCHDecimal = TPCHDecimal(0); const DISCOUNT_MAX: TPCHDecimal = TPCHDecimal(10); const PART_KEY_MIN: i32 = 1;
1871
1872 const SHIP_DATE_MIN: i32 = 1;
1873 const SHIP_DATE_MAX: i32 = 121;
1874 const COMMIT_DATE_MIN: i32 = 30;
1875 const COMMIT_DATE_MAX: i32 = 90;
1876 const RECEIPT_DATE_MIN: i32 = 1;
1877 const RECEIPT_DATE_MAX: i32 = 30;
1878
1879 pub const ITEM_SHIP_DAYS: i32 = Self::SHIP_DATE_MAX + Self::RECEIPT_DATE_MAX;
1880
1881 const COMMENT_AVERAGE_LENGTH: i32 = 27;
1882
1883 pub fn new(scale_factor: f64, part: i32, part_count: i32) -> LineItemGenerator<'static> {
1888 Self::new_with_distributions_and_text_pool(
1889 scale_factor,
1890 part,
1891 part_count,
1892 Distributions::static_default(),
1893 TextPool::get_or_init_default(),
1894 )
1895 }
1896
1897 pub fn new_with_distributions_and_text_pool<'b>(
1899 scale_factor: f64,
1900 part: i32,
1901 part_count: i32,
1902 distributions: &'b Distributions,
1903 text_pool: &'b TextPool,
1904 ) -> LineItemGenerator<'b> {
1905 LineItemGenerator {
1906 scale_factor,
1907 part,
1908 part_count,
1909 distributions,
1910 text_pool,
1911 }
1912 }
1913
1914 pub fn iter(&self) -> LineItemGeneratorIterator<'a> {
1916 LineItemGeneratorIterator::new(
1917 self.distributions,
1918 self.text_pool,
1919 self.scale_factor,
1920 GenerateUtils::calculate_start_index(
1921 OrderGenerator::SCALE_BASE,
1922 self.scale_factor,
1923 self.part,
1924 self.part_count,
1925 ),
1926 GenerateUtils::calculate_row_count(
1927 OrderGenerator::SCALE_BASE,
1928 self.scale_factor,
1929 self.part,
1930 self.part_count,
1931 ),
1932 )
1933 }
1934
1935 pub fn create_quantity_random() -> RandomBoundedInt {
1937 RandomBoundedInt::new_with_seeds_per_row(
1938 209208115,
1939 Self::QUANTITY_MIN,
1940 Self::QUANTITY_MAX,
1941 OrderGenerator::LINE_COUNT_MAX,
1942 )
1943 }
1944
1945 pub fn create_discount_random() -> RandomBoundedInt {
1947 RandomBoundedInt::new_with_seeds_per_row(
1948 554590007,
1949 Self::DISCOUNT_MIN.0 as i32,
1950 Self::DISCOUNT_MAX.0 as i32,
1951 OrderGenerator::LINE_COUNT_MAX,
1952 )
1953 }
1954
1955 pub fn create_tax_random() -> RandomBoundedInt {
1957 RandomBoundedInt::new_with_seeds_per_row(
1958 721958466,
1959 Self::TAX_MIN.0 as i32,
1960 Self::TAX_MAX.0 as i32,
1961 OrderGenerator::LINE_COUNT_MAX,
1962 )
1963 }
1964
1965 pub fn create_part_key_random(scale_factor: f64) -> RandomBoundedLong {
1967 RandomBoundedLong::new_with_seeds_per_row(
1970 1808217256,
1971 scale_factor >= 30000.0,
1972 Self::PART_KEY_MIN as i64,
1973 (PartGenerator::SCALE_BASE as f64 * scale_factor) as i64,
1974 OrderGenerator::LINE_COUNT_MAX,
1975 )
1976 }
1977
1978 pub fn create_ship_date_random() -> RandomBoundedInt {
1980 RandomBoundedInt::new_with_seeds_per_row(
1981 1769349045,
1982 Self::SHIP_DATE_MIN,
1983 Self::SHIP_DATE_MAX,
1984 OrderGenerator::LINE_COUNT_MAX,
1985 )
1986 }
1987}
1988
1989impl<'a> IntoIterator for &'a LineItemGenerator<'a> {
1990 type Item = LineItem<'a>;
1991 type IntoIter = LineItemGeneratorIterator<'a>;
1992
1993 fn into_iter(self) -> Self::IntoIter {
1994 self.iter()
1995 }
1996}
1997
1998#[derive(Debug)]
2000pub struct LineItemGeneratorIterator<'a> {
2001 order_date_random: RandomBoundedInt,
2002 line_count_random: RandomBoundedInt,
2003
2004 quantity_random: RandomBoundedInt,
2005 discount_random: RandomBoundedInt,
2006 tax_random: RandomBoundedInt,
2007
2008 line_part_key_random: RandomBoundedLong,
2009
2010 supplier_number_random: RandomBoundedInt,
2011
2012 ship_date_random: RandomBoundedInt,
2013 commit_date_random: RandomBoundedInt,
2014 receipt_date_random: RandomBoundedInt,
2015
2016 returned_flag_random: RandomString<'a>,
2017 ship_instructions_random: RandomString<'a>,
2018 ship_mode_random: RandomString<'a>,
2019
2020 comment_random: RandomText<'a>,
2021
2022 scale_factor: f64,
2023 start_index: i64,
2024 row_count: i64,
2025
2026 index: i64,
2027 order_date: i32,
2028 line_count: i32,
2029 line_number: i32,
2030}
2031
2032impl<'a> LineItemGeneratorIterator<'a> {
2033 fn new(
2034 distributions: &'a Distributions,
2035 text_pool: &'a TextPool,
2036 scale_factor: f64,
2037 start_index: i64,
2038 row_count: i64,
2039 ) -> Self {
2040 let mut order_date_random = OrderGenerator::create_order_date_random();
2041 let mut line_count_random = OrderGenerator::create_line_count_random();
2042
2043 let mut quantity_random = LineItemGenerator::create_quantity_random();
2044 let mut discount_random = LineItemGenerator::create_discount_random();
2045 let mut tax_random = LineItemGenerator::create_tax_random();
2046
2047 let mut line_part_key_random = LineItemGenerator::create_part_key_random(scale_factor);
2048
2049 let mut supplier_number_random = RandomBoundedInt::new_with_seeds_per_row(
2050 2095021727,
2051 0,
2052 3,
2053 OrderGenerator::LINE_COUNT_MAX,
2054 );
2055
2056 let mut ship_date_random = LineItemGenerator::create_ship_date_random();
2057 let mut commit_date_random = RandomBoundedInt::new_with_seeds_per_row(
2058 904914315,
2059 LineItemGenerator::COMMIT_DATE_MIN,
2060 LineItemGenerator::COMMIT_DATE_MAX,
2061 OrderGenerator::LINE_COUNT_MAX,
2062 );
2063 let mut receipt_date_random = RandomBoundedInt::new_with_seeds_per_row(
2064 373135028,
2065 LineItemGenerator::RECEIPT_DATE_MIN,
2066 LineItemGenerator::RECEIPT_DATE_MAX,
2067 OrderGenerator::LINE_COUNT_MAX,
2068 );
2069
2070 let mut returned_flag_random = RandomString::new_with_expected_row_count(
2071 717419739,
2072 distributions.return_flags(),
2073 OrderGenerator::LINE_COUNT_MAX,
2074 );
2075 let mut ship_instructions_random = RandomString::new_with_expected_row_count(
2076 1371272478,
2077 distributions.ship_instructions(),
2078 OrderGenerator::LINE_COUNT_MAX,
2079 );
2080 let mut ship_mode_random = RandomString::new_with_expected_row_count(
2081 675466456,
2082 distributions.ship_modes(),
2083 OrderGenerator::LINE_COUNT_MAX,
2084 );
2085 let mut comment_random = RandomText::new_with_expected_row_count(
2086 1095462486,
2087 text_pool,
2088 LineItemGenerator::COMMENT_AVERAGE_LENGTH as f64,
2089 OrderGenerator::LINE_COUNT_MAX,
2090 );
2091
2092 order_date_random.advance_rows(start_index);
2094 line_count_random.advance_rows(start_index);
2095
2096 quantity_random.advance_rows(start_index);
2097 discount_random.advance_rows(start_index);
2098 tax_random.advance_rows(start_index);
2099
2100 line_part_key_random.advance_rows(start_index);
2101
2102 supplier_number_random.advance_rows(start_index);
2103
2104 ship_date_random.advance_rows(start_index);
2105 commit_date_random.advance_rows(start_index);
2106 receipt_date_random.advance_rows(start_index);
2107
2108 returned_flag_random.advance_rows(start_index);
2109 ship_instructions_random.advance_rows(start_index);
2110 ship_mode_random.advance_rows(start_index);
2111
2112 comment_random.advance_rows(start_index);
2113
2114 let order_date = order_date_random.next_value();
2116 let line_count = line_count_random.next_value() - 1;
2117
2118 LineItemGeneratorIterator {
2119 order_date_random,
2120 line_count_random,
2121 quantity_random,
2122 discount_random,
2123 tax_random,
2124 line_part_key_random,
2125 supplier_number_random,
2126 ship_date_random,
2127 commit_date_random,
2128 receipt_date_random,
2129 returned_flag_random,
2130 ship_instructions_random,
2131 ship_mode_random,
2132 comment_random,
2133 scale_factor,
2134 start_index,
2135 row_count,
2136 index: 0,
2137 order_date,
2138 line_count,
2139 line_number: 0,
2140 }
2141 }
2142
2143 fn make_line_item(&mut self, order_index: i64) -> LineItem<'a> {
2145 let order_key = OrderGenerator::make_order_key(order_index);
2146
2147 let quantity = self.quantity_random.next_value();
2148 let discount = self.discount_random.next_value();
2149 let tax = self.tax_random.next_value();
2150
2151 let part_key = self.line_part_key_random.next_value();
2152
2153 let supplier_number = self.supplier_number_random.next_value() as i64;
2154 let supplier_key = PartSuppGeneratorIterator::select_part_supplier(
2155 part_key,
2156 supplier_number,
2157 self.scale_factor,
2158 );
2159
2160 let part_price = PartGeneratorIterator::calculate_part_price(part_key);
2161 let extended_price = part_price * quantity as i64;
2162
2163 let mut ship_date = self.ship_date_random.next_value();
2164 ship_date += self.order_date;
2165 let mut commit_date = self.commit_date_random.next_value();
2166 commit_date += self.order_date;
2167 let mut receipt_date = self.receipt_date_random.next_value();
2168 receipt_date += ship_date;
2169
2170 let returned_flag = if TPCHDate::is_in_past(receipt_date) {
2171 self.returned_flag_random.next_value()
2172 } else {
2173 "N"
2174 };
2175
2176 let status = if TPCHDate::is_in_past(ship_date) {
2177 "F" } else {
2179 "O" };
2181
2182 let ship_instructions = self.ship_instructions_random.next_value();
2183 let ship_mode = self.ship_mode_random.next_value();
2184 let comment = self.comment_random.next_value();
2185
2186 LineItem {
2187 l_orderkey: order_key,
2188 l_partkey: part_key,
2189 l_suppkey: supplier_key,
2190 l_linenumber: (self.line_number + 1),
2191 l_quantity: quantity as i64,
2192 l_extendedprice: TPCHDecimal(extended_price),
2193 l_discount: TPCHDecimal(discount as i64),
2194 l_tax: TPCHDecimal(tax as i64),
2195 l_returnflag: returned_flag,
2196 l_linestatus: status,
2197 l_shipdate: TPCHDate::new(ship_date),
2198 l_commitdate: TPCHDate::new(commit_date),
2199 l_receiptdate: TPCHDate::new(receipt_date),
2200 l_shipinstruct: ship_instructions,
2201 l_shipmode: ship_mode,
2202 l_comment: comment,
2203 }
2204 }
2205}
2206
2207impl<'a> Iterator for LineItemGeneratorIterator<'a> {
2208 type Item = LineItem<'a>;
2209
2210 fn next(&mut self) -> Option<Self::Item> {
2211 if self.index >= self.row_count {
2212 return None;
2213 }
2214
2215 let line_item = self.make_line_item(self.start_index + self.index + 1);
2216 self.line_number += 1;
2217
2218 if self.line_number > self.line_count {
2220 self.order_date_random.row_finished();
2221 self.line_count_random.row_finished();
2222
2223 self.quantity_random.row_finished();
2224 self.discount_random.row_finished();
2225 self.tax_random.row_finished();
2226
2227 self.line_part_key_random.row_finished();
2228 self.supplier_number_random.row_finished();
2229
2230 self.ship_date_random.row_finished();
2231 self.commit_date_random.row_finished();
2232 self.receipt_date_random.row_finished();
2233
2234 self.returned_flag_random.row_finished();
2235 self.ship_instructions_random.row_finished();
2236 self.ship_mode_random.row_finished();
2237
2238 self.comment_random.row_finished();
2239
2240 self.index += 1;
2241
2242 self.line_count = self.line_count_random.next_value() - 1;
2244 self.order_date = self.order_date_random.next_value();
2245 self.line_number = 0;
2246 }
2247
2248 Some(line_item)
2249 }
2250}
2251
2252#[cfg(test)]
2253mod tests {
2254 use super::*;
2255
2256 #[test]
2257 fn test_nation_generator() {
2258 let generator = NationGenerator::default();
2259 let nations: Vec<_> = generator.iter().collect();
2260
2261 assert_eq!(nations.len(), 25);
2263 }
2264
2265 #[test]
2266 fn test_region_generator() {
2267 let generator = RegionGenerator::default();
2268 let regions: Vec<_> = generator.iter().collect();
2269
2270 assert_eq!(regions.len(), 5);
2272 }
2273
2274 #[test]
2275 fn test_part_generation() {
2276 let generator = PartGenerator::new(0.01, 1, 1);
2278 let parts: Vec<_> = generator.iter().collect();
2279
2280 assert_eq!(parts.len(), 2000);
2282 }
2283
2284 #[test]
2285 fn test_calculate_part_price() {
2286 assert_eq!(PartGeneratorIterator::calculate_part_price(1), 90100);
2288 assert_eq!(PartGeneratorIterator::calculate_part_price(10), 91001);
2289 assert_eq!(PartGeneratorIterator::calculate_part_price(100), 100010);
2290 assert_eq!(PartGeneratorIterator::calculate_part_price(1000), 90100);
2291 }
2292
2293 #[test]
2294 fn test_supplier_generation() {
2295 let generator = SupplierGenerator::new(0.01, 1, 1);
2297 let suppliers: Vec<_> = generator.iter().collect();
2298
2299 assert_eq!(suppliers.len(), 100);
2301
2302 let first = &suppliers[0];
2304 assert_eq!(first.s_suppkey, 1);
2305 assert_eq!(first.to_string(), "1|Supplier#000000001| N kD4on9OM Ipw3,gf0JBoQDd7tgrzrddZ|17|27-918-335-1736|5755.94|each slyly above the careful|")
2306 }
2307
2308 #[test]
2309 fn test_customer_generation() {
2310 let generator = CustomerGenerator::new(0.01, 1, 1);
2312 let customers: Vec<_> = generator.iter().collect();
2313
2314 assert_eq!(customers.len(), 1500);
2316
2317 let first = &customers[0];
2319 assert_eq!(first.c_custkey, 1);
2320 assert_eq!(first.to_string(), "1|Customer#000000001|IVhzIApeRb ot,c,E|15|25-989-741-2988|711.56|BUILDING|to the even, regular platelets. regular, ironic epitaphs nag e|");
2321
2322 let market_segments: std::collections::HashSet<_> =
2324 customers.iter().map(|c| &c.c_mktsegment).collect();
2325
2326 assert!(market_segments.len() > 1);
2328
2329 let nation_keys: std::collections::HashSet<_> =
2331 customers.iter().map(|c| c.c_nationkey).collect();
2332
2333 assert!(nation_keys.len() > 1);
2335 }
2336
2337 #[test]
2338 fn test_part_supplier_generation() {
2339 let generator = PartSuppGenerator::new(0.01, 1, 1);
2341 let part_suppliers: Vec<_> = generator.iter().collect();
2342
2343 assert_eq!(part_suppliers.len(), 8000);
2345
2346 let part_keys: std::collections::HashSet<_> =
2348 part_suppliers.iter().map(|ps| ps.ps_partkey).collect();
2349
2350 assert_eq!(part_keys.len(), 2000); let first = &part_suppliers[0];
2354 assert_eq!(first.ps_partkey, 1);
2355 assert_ne!(first.ps_suppkey, 0); assert!(first.ps_availqty > 0);
2357 assert!(first.ps_supplycost > TPCHDecimal::ZERO);
2358 assert!(!first.ps_comment.is_empty());
2359
2360 let suppliers_for_first_part: Vec<_> = part_suppliers
2362 .iter()
2363 .filter(|ps| ps.ps_partkey == 1)
2364 .map(|ps| ps.ps_suppkey)
2365 .collect();
2366
2367 assert_eq!(
2368 suppliers_for_first_part.len(),
2369 PartSuppGenerator::SUPPLIERS_PER_PART as usize
2370 );
2371
2372 let unique_suppliers: std::collections::HashSet<_> =
2374 suppliers_for_first_part.iter().collect();
2375 assert_eq!(
2376 unique_suppliers.len(),
2377 PartSuppGenerator::SUPPLIERS_PER_PART as usize
2378 );
2379 }
2380
2381 #[test]
2382 fn test_select_part_supplier() {
2383 let scale_factor = 1.0;
2385
2386 let supplier1 = PartSuppGeneratorIterator::select_part_supplier(1, 0, scale_factor);
2388 let supplier2 = PartSuppGeneratorIterator::select_part_supplier(1, 1, scale_factor);
2389 let supplier3 = PartSuppGeneratorIterator::select_part_supplier(1, 2, scale_factor);
2390 let supplier4 = PartSuppGeneratorIterator::select_part_supplier(1, 3, scale_factor);
2391
2392 let suppliers = vec![supplier1, supplier2, supplier3, supplier4];
2394 let unique_suppliers: std::collections::HashSet<_> = suppliers.iter().collect();
2395 assert_eq!(
2396 unique_suppliers.len(),
2397 PartSuppGenerator::SUPPLIERS_PER_PART as usize
2398 );
2399
2400 let supplier_count = (SupplierGenerator::SCALE_BASE as f64 * scale_factor) as i64;
2402 for supplier in suppliers {
2403 assert!(supplier >= 1 && supplier <= supplier_count);
2404 }
2405 }
2406
2407 #[test]
2408 fn test_order_generation() {
2409 let generator = OrderGenerator::new(0.01, 1, 1);
2411 let orders: Vec<_> = generator.iter().collect();
2412
2413 assert_eq!(orders.len(), 15000);
2415
2416 let first = &orders[0];
2418 assert_eq!(first.o_orderkey, OrderGenerator::make_order_key(1));
2419 assert!(first.o_custkey > 0);
2420 assert!(first.o_totalprice > TPCHDecimal::ZERO);
2421
2422 let status_counts =
2424 orders
2425 .iter()
2426 .fold(std::collections::HashMap::new(), |mut acc, order| {
2427 *acc.entry(&order.o_orderstatus).or_insert(0) += 1;
2428 acc
2429 });
2430
2431 assert!(status_counts.len() >= 2);
2433
2434 assert!(orders
2436 .iter()
2437 .all(|o| o.o_custkey % OrderGenerator::CUSTOMER_MORTALITY as i64 != 0));
2438
2439 for (i, order) in orders.iter().enumerate() {
2441 assert_eq!(
2442 order.o_orderkey,
2443 OrderGenerator::make_order_key(i as i64 + 1)
2444 );
2445 }
2446 }
2447
2448 #[test]
2449 fn test_make_order_key() {
2450 assert_eq!(OrderGenerator::make_order_key(1), 1); assert_eq!(OrderGenerator::make_order_key(8), 32); assert_eq!(OrderGenerator::make_order_key(9), 32 + 1); assert_eq!(OrderGenerator::make_order_key(10), 32 + 2); }
2456
2457 #[test]
2458 fn test_line_item_generation() {
2459 let generator = LineItemGenerator::new(0.01, 1, 1);
2461 let line_items: Vec<_> = generator.iter().collect();
2462
2463 let first = &line_items[0];
2465 assert_eq!(first.l_orderkey, OrderGenerator::make_order_key(1));
2466 assert_eq!(first.l_linenumber, 1);
2467 assert!(first.l_partkey > 0);
2468 assert!(first.l_suppkey > 0);
2469
2470 assert!(first.l_quantity >= LineItemGenerator::QUANTITY_MIN as i64);
2471 assert!(first.l_quantity <= LineItemGenerator::QUANTITY_MAX as i64);
2472
2473 assert!(first.l_discount >= LineItemGenerator::DISCOUNT_MIN);
2474 assert!(first.l_discount <= LineItemGenerator::DISCOUNT_MAX);
2475
2476 assert!(first.l_tax >= LineItemGenerator::TAX_MIN);
2477 assert!(first.l_tax <= LineItemGenerator::TAX_MAX);
2478
2479 let mut order_lines = std::collections::HashMap::new();
2481 for line in &line_items {
2482 order_lines
2483 .entry(line.l_orderkey)
2484 .or_insert_with(Vec::new)
2485 .push(line.l_linenumber);
2486 }
2487
2488 for (_, lines) in order_lines {
2490 let mut sorted_lines = lines.clone();
2491 sorted_lines.sort();
2492
2493 for (i, line_num) in sorted_lines.iter().enumerate() {
2495 assert_eq!(*line_num, (i + 1) as i32);
2496 }
2497 }
2498
2499 let return_flags: std::collections::HashSet<_> =
2501 line_items.iter().map(|l| &l.l_returnflag).collect();
2502
2503 assert!(return_flags.len() > 1);
2504
2505 let line_statuses: std::collections::HashSet<_> =
2506 line_items.iter().map(|l| &l.l_linestatus).collect();
2507
2508 assert!(!line_statuses.is_empty());
2509 }
2510
2511 #[test]
2512 fn check_iter_static_lifetimes() {
2513 let _iter: NationGeneratorIterator<'static> = NationGenerator::default().iter();
2517 let _iter: RegionGeneratorIterator<'static> = RegionGenerator::default().iter();
2518 let _iter: PartGeneratorIterator<'static> = PartGenerator::new(0.1, 1, 1).iter();
2519 let _iter: SupplierGeneratorIterator<'static> = SupplierGenerator::new(0.1, 1, 1).iter();
2520 let _iter: CustomerGeneratorIterator<'static> = CustomerGenerator::new(0.1, 1, 1).iter();
2521 let _iter: PartSuppGeneratorIterator<'static> = PartSuppGenerator::new(0.1, 1, 1).iter();
2522 let _iter: OrderGeneratorIterator<'static> = OrderGenerator::new(0.1, 1, 1).iter();
2523 let _iter: LineItemGeneratorIterator<'static> = LineItemGenerator::new(0.1, 1, 1).iter();
2524 }
2525}